Just the other day I asked a question about nesting queries together - in a nutshell it was about how to pull data from two different related tables when there may or may not be linked rows in a second table. That led me down the path to LEFT/RIGHT JOINS and was easy to pick up. Now, however I am coming across an entirely new problem, and this is stumping me.
When one pulls back information using LEFT/RIGHT JOINS (let's assume that it's just a LEFT JOIN for the rest of this question), in the scenario where there are multiple matching rows in Table B, Table A's information is pulled back each time a match in Table B is found, and this results in entirely new rows being pulled back as well. Is there a way to aggregate the information from Table B when doing LEFT JOINS?
For example, let's say that we have a products table with only one product row in it and an images table, which has 6 image rows, all linked to the one product in the products table.
Let's say that we then use the query:
SELECT product_name, large_image, medium_image FROM products
LEFT JOIN images ON images.image_product_Id = products.productId
This will pull back 6 rows, with repeated information for the product_name in each row, but unique information for the large_image and medium_image.
Is there a way to pull back this information in one row, with the rows from the images table nested? The result returning one row, and the image information for the 6 images in an associative array that is pulled back as a column?
Ideally, this information would come back as :
[
1 => [ product_name => 'Apple iPhone',
images => [
{
large_image=>'image1.jpg',
'medium_image'=>'image1_m.jpg'
},
{
large_image=>'image2.jpg',
medium_image=>'image2_m.jpg'}
...
]
]
]
The only solution I can currently think of is to pull the information for the products back in one query:
SELECT product_name, productId FROM products
and while iterating over that information, making subsequent queries to the database for each row to get all the images for that product:
SELECT large_image, medium_image FROM images WHERE images.image_product_Id
= '$productId'
where '$productId' is the parameter I am feeding the second query, and which represents the productId column from the first query. This seems not only inefficient, but bad programming practice. Could someone point me in the right direction?
I hope I was able to word this clearly - if not, please let me know what I can do word it better!
Thanks in advance :)
As per your question I found an answer that works for you, see the below SQL.
SELECT product_name,
GROUP_CONCAT(DISTINCT large_image) AS LargeImages,
GROUP_CONCAT(DISTINCT medium_image) AS medium_images
FROM products
LEFT JOIN images ON images.image_product_Id = products.productId
GROUP BY productId
Related
I have been trying to get this code working for almost six hours an I have done almost six hours worth of research.
Originally this code was to be outputted from a database through PHP to a CSV file..
All I am trying to do is have three different tables and have them all joined together by their order_ID
Every time I keep trying to do this in PHP my admin either the code comes out weird in the output is not joining correctly or is giving some sort of strange error. Any help that anyone could figure out what is going on with this would be greatly appreciated
SELECT
oc_order.store_url,
oc_order.order_id,
oc_order.firstname,
oc_order.lastname,
oc_order.email,
oc_order_option.order_id,
oc_order_option.name,
oc_order_option.value,
oc_order_product.order_id,
oc_order_product.name,
oc_order_product.model,
oc_order_product.quantity
FROM oc_order, oc_order_option , oc_order_product
ORDER BY oc_order.order_id,oc_order_option.order_id,oc_order_product.order_id
As mentioned, you are missing your ON clauses. When you are using multiple tables in a SQL query, you have your LEFT table (first table in from clause) being JOINed to the second (right table). The "ON" clause tells how table 1 is related to table 2. And in your case, you have a table 3. Is this a relationship between table 1 to 3 or from table 2 to 3. I will update the query, you will need to fill in the blanks a bit since you have not shown structures. Also, using table aliases makes code more readable, especially if table names get long. You'll see in a moment.
SELECT
o.store_url,
o.order_id,
o.firstname,
o.lastname,
o.email,
oOp.order_id,
oOp.name,
oOp.value,
p.order_id,
p.name,
p.model,
p.quantity
FROM
oc_order o
JOIN oc_order_option oOp
on o.order_id = oOp.order_id
JOIN oc_order_product p
on o.order_id = p.order_id
ORDER BY
o.order_id
Notice the abbreviated aliases for the table names "o" for oc_orders, "oOp" for oc_order_option and "p" for oc_order_product
Again, YOU need to confirm the "ON" clauses on the left-table is associated with the right table. I have worked with manufacturing in the past and have seen that someone orders. Purchases a product, and that product has options, so Is there something on the order's detail line for the specific product that has an ID to the order OPTIONS table. That is where you probably need to focus. Again, other systems I have had, would have had a hierarchy something like
Order
Customer (who ordered)
OrderDetails (what of multiple products were ordered)
Product ( per orderDetail, what was the product)
ProductOption (color,size,etc)
See the hierarchical representation? In this scenario, you dont go just from Order table to the Product option. You have to get to the details to the product to the product's option. Anyway, HTH
I'm trying to build a review record based on fields from 5 tables:
I've marked all the columns I need, but for the moment I'm just retrieving all of the user_rating table.
Here's what I have so far:
SELECT DISTINCT user_rating.*, whiskey.name, user_notes.overall, users.image, user_rate.rate_number
FROM user_rating
LEFT JOIN whiskey ON whiskey.id = user_rating.whiskeyid
LEFT JOIN users ON users.username = user_rating.username
LEFT JOIN user_notes ON user_notes.username = user_rating.username AND user_rating.whiskeyid = user_notes.whiskey_id
LEFT JOIN user_rate ON user_rate.whiskey_id = user_rating.whiskeyid AND user_rate.username = user_rating.username
ORDER BY user_rating.id DESC
At first I thought this was giving me the results I wanted but then I noticed I was getting multiple rows as well as too many null fields. Any help would be greatly appreciated.
Edit:
By multiple rows I mean duplicate rows. Also, I am aware that a left join produces null values on the right side of the join. What I meant to say is that I'm getting more null values than I should be as the data is within the database.
To clarify, I'm trying to create a list of recent reviews with the most recent listed first. Each review consists of a username, 11 categories (each one is an integer value), overall rating (int value), notes (string), image (URL), and whiskey name (string).
1) You can't be getting multiple SAME rows, since you use DISTINCT. (by multiple do you mean duplicate?)
2) You get null fields because you are using LEFT JOIN and your tables cannot be joined (some "ON clause" cannot be evaluated as true)
It turns out that there was nothing wrong with my query. The person whose database I'm using isn't maintaining it so there are several reviews for the same product and user where only the overall rating is different. Also, there are many reviews on products that don't even exist. I should've looked at the database closer to begin with as deleting all of the erroneous rows solved my problem. Thanks for all the input.
I am building an auction website. Right now, I am building the item description page, that has item details, as well as current bid history. My bids table has a FK of Item_id.
My current query looks something like this:
SELECT bids.Item_id, bids.User_email, bids.Bid_amount, products.*
FROM bids
INNER JOIN products
ON bids.Item_id=products.Item_id;
This returns all of the bid information I need - but also returns the item description for every bid row. I only need the product information once. Is it best to just use two queries on this?
Any help is appreciated
If you need the bids data separately from the products data, then you should use two queries.
One query cannot really be arrange to return different columns for different rows.
SELECT b.Item_id, b.User_email, b.Bid_amount, p.*
FROM bids b
INNER JOIN products p
ON b.Item_id=p.Item_id
WHERE p.Item_id=something;
This will not repeat products..
I am trying to query 2 tables in a database, each query having nothing to do with each other, other then being on the same page.
Query 1 - The first query on the page will retrieve text and images that are found throughout the page from Table A.
Query 2 - The second query will retrieve several products with a image, description and title for each product from Table B.
I know that putting the second query inside the first query's while loop would work but of course is very inefficient.
How can I and what is the best way to retrieve all the data I need through 1 query?
Thanks,
Dane
So all you want to know is if its ok to have 2 queries on the same webpage? Its A-OK. Go right ahead. Its completelly normal. No one expects a join between table news and table products. Its normal to usetwo queries to fetch data from two unrelated tables.
Use LEFT or INNER JOIN (depends on whether you want to display records from TableA that have no correspondent records in TableB)
SELECT a.*, b.*
FROM TableA a
[LEFT or INNER] JOIN TableB b ON (b.a_id = a.id)
If there's no way to relate the two tables to each other, then you can't use a JOIN to grab records from both. You COULD use a UNION query, but that presumes that you can match up fields from each table, as a UNION requires you to select the same number/type of fields from each table.
SELECT 'pageinfo' AS sourcetable, page.id, page.images, page.this, page.that
WHERE page.id = $id
UNION
SELECT 'product' AS sourcetable, products.id, products.image, product.other, product.stuff
But this is highly ugly. You're still forcing the DB server to do two queries in the background plus the extra work of combining them into a single result set, and then you have to do extra work to dis-entangle in your code to boot.
It's MUCH easier, conceptually and maintenance-wise, to do two seperate queries instead.
I have a products table with a column that contains a space separated list of ids (like: "23 42 365"), the column is called "categories". The numbers refer to rows ids in another table (categories).
I need to extract all product rows where all of the ids in the space separated list point to rows on the categories table that no longer exist.
I know this is not the best database design by a long way, however I have been presented with this task on an older system. I am not even sure it can be done entirely with an SQL statement, but because of the sheer number of records on the product table, it would be slower to use PHP logic to determine the rows to return. However, if thats the only way, thats what i'll do!
SELECT m.*
FROM mytable m
LEFT JOIN
categories c
ON FIND_IN_SET(c.id, REPLACE(m.categories, ' ', ','))
WHERE c.id IS NULL
You can use an outer join to get the missing rows, searching for where the category is null.
http://dev.mysql.com/doc/refman/5.0/en/join.html