I have 3 tables products,colors,assign with this structure:
products:
product_id | default_color
1 | 1
colors
color_id | color_name
1 | Black
2 | Green
3 | Yellow
assign
product_id | color_id
1 | 1
1 | 2
1 | 3
My query returns only first row from "assign" table, I need to have ALL colors assigned for current product.
Here is a query I use:
SELECT * FROM products p
LEFT JOIN assign a ON p.product_id = '1'
LEFT JOIN colors c ON a.color_id = c.color_id
WHERE p.product_id = 1
Try this:
SELECT * FROM products p
LEFT JOIN assign a ON a.product_id = p.product_id
LEFT JOIN colors c ON c.color_id = a.color_id
WHERE p.product_id = 1
The join condition should be made on column names, not on values.
For filtering results, use where.
See here a working sqlFiddle.
For more info on join, see the official docs here.
Instead of p.product_id = '1' use a.product_id
SELECT * FROM products p
LEFT JOIN assign a ON p.product_id = a.product_id
LEFT JOIN colors c ON a.color_id = c.color_id
WHERE p.product_id = 1`
Your SQL statement seems to list all three rows from assign table.
I executed your query:
SELECT * FROM products p
LEFT JOIN assign a ON p.product_id = '1'
LEFT JOIN colors c ON a.color_id = c.color_id
WHERE p.product_id = 1
And I am getting the three rows of assign table.
Here is my SQLFiddle: http://sqlfiddle.com/#!9/50f8bd/1/0
Try this query. Everything is the same as yours except I'm using GROUP_CONCAT() function to concatinate ALL colors for a given product into one field.
SELECT
p.product_id,
GROUP_CONCAT(c.color_name ORDER BY c.color_name ASC SEPARATOR ', ') AS colors
FROM products p
LEFT JOIN assign a ON a.product_id = p.product_id
LEFT JOIN colors c ON c.color_id = a.color_id
WHERE p.product_id = 1
RESULT:
product_id | colors
-----------|-------------
1 | Black, Green, Yellow
DEMO:
http://sqlfiddle.com/#!9/50f8bd/6
Related
So im just wondering if the next is possible and if so how to approach this.
I created an INNER JOIN query to SELECT multiple ID's from on a table where it is equal to the ID value from another table.
Product table
product_id | cults_id1 | cults_id2 | cults_id3
-----------------------------------------------------
1 | 5 | 4 | 2
2 | 3 | 0 | 0
Cultivar table
cults_id | cults_name |
---------------------------
1 | berries |
2 | fruit |
3 | choc |
4 | wood |
5 | mysql! |
So i created an join where it will fetch all the cults_name based on the product tables cults_id1, cults_id2, cults_id3
Result:
Product_id(1) = mysql! , wood , fruit
Now the problem comes with the next one how can i display the one value that product_id(2) contains.
So it would result in looking like this:
Product_id(1) = mysql! , wood , fruit
Product_id(2) = choc
At this moment product_id(2) wont display in my listing because it has no resemble to the Cultivar table after the first ID, (using this query).
I know normalisation should be considered.
Query
SELECT p.product_image_path, p.product_id, p.brand_name, p.product_name, b.botttle_size, v.vintage,
t.wine_type_blend, p.price, p.quantity, p.time_created, p.reference_number, p.shipping_cost,
c1.cultivar_type as cultivar_type1, c2.cultivar_type as cultivar_type2,
c3.cultivar_type as cultivar_type3, c4.cultivar_type as cultivar_type4
FROM product p
INNER JOIN wine_bottle b ON b.bottle_id = p.bottle_id
INNER JOIN wine_vintage v ON v.vintage_id = p.vintage_id
INNER JOIN wine_type t ON t.type_id = p.type_id
INNER JOIN wine_cultivar c1 ON c1.cultivar_id = p.cultivar_1_id
INNER JOIN wine_cultivar c2 ON c2.cultivar_id = p.cultivar_2_id
INNER JOIN wine_cultivar c3 ON c3.cultivar_id = p.cultivar_3_id
INNER JOIN wine_cultivar c4 ON c4.cultivar_id = p.cultivar_4_id
Now my product listing page has this to display it in listing but i want to display even if cults_id1, cults_id2, cults_id3 has an value of 0.
Product-listing.php
<?php
if($result = mysqli_query($conn, $query)){
if(mysqli_num_rows($result) > 0){
$i = 0;
while($row = mysqli_fetch_array($result)){
$i++;
echo "
<p>Cultivars: <span>" .$row["cultivar_type1"]. "</span>, <span>" .$row["cultivar_type2"]. "</span>, <span>" .$row["cultivar_type3"]. "</span>, <span>" .$row["cultivar_type4"]. "</span></p> ";
}
mysqli_free_result($result);
}
}
Output:
Product_id(1) = mysql! , wood , fruit
Expected:
Product_id(1) = mysql! , wood , fruit
Product_id(2) = choc
So the only thing that i needed to to was to create an LEFT JOIN. Because an LEFT JOIN can accept 0 or an value. And my query worked.
Yes this my mysql DB is not the normalized as would be expected.
Solution:
SELECT p.product_image_path, p.product_id, p.brand_name, p.product_name, b.botttle_size, v.vintage,
t.wine_type_blend, p.price, p.quantity, p.time_created,
p.reference_number, p.shipping_cost,
c1.cultivar_type as cultivar_type1, c2.cultivar_type as cultivar_type2,
c3.cultivar_type as cultivar_type3, c4.cultivar_type as cultivar_type4
FROM product p
INNER JOIN wine_bottle b ON b.bottle_id = p.bottle_id
INNER JOIN wine_vintage v ON v.vintage_id = p.vintage_id
INNER JOIN wine_type t ON t.type_id = p.type_id
LEFT JOIN wine_cultivar c1 ON c1.cultivar_id = p.cultivar_1_id
LEFT JOIN wine_cultivar c2 ON c2.cultivar_id = p.cultivar_2_id
LEFT JOIN wine_cultivar c3 ON c3.cultivar_id = p.cultivar_3_id
LEFT JOIN wine_cultivar c4 ON c4.cultivar_id = p.cultivar_4_id
I have an table called product which lets say looks like this:
product
product_id | cults_id1 | cults_id2 | cults_id3
-----------------------------------------------------
1 | 5 | 4 | 2
And the also a table thats based on this called cultivar:
cultivar
cults_id | cults_name |
-------------------------
1 | berries |
2 | fruit |
3 | choc |
4 | wood |
5 | mysql! |
How would i create an JOIN query to get each name from cultivar table where the product id in product table is the same as cults_id in the cultivar table?
OUTPUT
My Product Cults :
berries, Mysql!, wood, fruit
Dont think an INNER JOIN is the way to go but i would have tried something like this:
$query = "SELECT cultivars.cults_name
FROM product
INNER JOIN wine_cultivar ON wine_cultivar.cults_id = product.cultivar_1_id
INNER JOIN wine_cultivar ON wine_cultivar.cults_id = product.cultivar_2_id
INNER JOIN wine_cultivar ON wine_cultivar.cults_id = product.cultivar_3_id
INNER JOIN wine_cultivar ON wine_cultivar.cults_id = product.cultivar_4_id
";
i tried a inner join multiple times targeting all the ids but dont think this is the way to go. Also this is just a part of my sql query.
Simply assign table aliases to each self join and then reference corresponding fields in SELECT.
Right now you join to same table but do not provide aliases to distinguish between the four which MySQL should have raised its Error #1066 for this attempt.
SELECT p.product_image_path, p.product_id, p.brand_name, p.product_name, b.botttle_size, v.vintage,
t.wine_type_blend, p.price, p.quantity, p.time_created, p.reference_number, p.shipping_cost,
c1.cultivar_type as cultivar_type1, c2.cultivar_type as cultivar_type2,
c3.cultivar_type as cultivar_type3, c4.cultivar_type as cultivar_type4
FROM product p
INNER JOIN wine_bottle b ON b.bottle_id = p.bottle_id
INNER JOIN wine_vintage v ON v.vintage_id = p.vintage_id
INNER JOIN wine_type t ON t.type_id = p.type_id
INNER JOIN wine_cultivar c1 ON c1.cultivar_id = p.cultivar_1_id
INNER JOIN wine_cultivar c2 ON c2.cultivar_id = p.cultivar_2_id
INNER JOIN wine_cultivar c3 ON c3.cultivar_id = p.cultivar_3_id
INNER JOIN wine_cultivar c4 ON c4.cultivar_id = p.cultivar_4_id
I have 2 tables.
First table - products
products_id | quantity
1001,1
1002,2
1003,5
1004,4
Second table - products_catalog
products_catalog_id | products_id | partner_channel |active_status
1,1001,amazon,0
2,1001,ebay,0
3,1001,zalando,1
4,1002,amazon,1
5,1002,ebay,0
6,1003,amazon,1
7,1003,ebay,1
8,1003,zalando,1
9,1004,amazon,0
10,1004,ebay,0
11,1004,zalando,0
I want to have result of the products id with the condition if this product is not active in any partner channel (active_status = 0)
I was using WHERE filter like this:
SELECT p.products_id, pc.partner_channel, pc.active_status
FROM products p
LEFT JOIN products_catalog pc ON pc.products_id=p.products_id
WHERE pc.active_status='0'
GROUP BY p.products_id ORDER BY p.products_id;
WHERE active_status = 0, but the result was like this:
products_id | partner_channel | active_status
1001,amazon,0
1002,ebay,0
1004,amazon,0
I want to have result table products like this:
products_id | partner_channel | active_status
1004,amazon,0
Because in all partner_channel only this product id (1004) that have active_status = 0.
I think i missed something in the WHERE filter, but didn't have any clue about that. Maybe i should use sub query in when LEFT JOIN to products_catalog?
Any help will be appreciated.
Thanks.
use Having function.
SELECT p.products_id, ANY_VALUE(pc.partner_channel), ANY_VALUE(pc.active_status)
FROM products p
LEFT JOIN products_catalog pc ON pc.products_id=p.products_id
GROUP BY p.products_id
having sum(pc.active_status)=0
ORDER BY p.products_id;
You have to place a condition in the HAVING clause like this:
SELECT products_id
FROM products_catalog
GROUP BY products_id
HAVING SUM(active_status <> 0) = 0;
This query returns all products_id values having active_status = 0 for all partner_channel they are related to.
You can then use the above query as a derived table to join back to the original tables in order to get the rest of the fields:
SELECT p.*, pc.*
FROM products p
JOIN products_catalog pc ON pc.products_id=p.products_id
JOIN (
SELECT products_id
FROM products_catalog
GROUP BY products_id
HAVING SUM(active_status <> 0) = 0
) AS g ON g.products_id = p.products_id
ORDER BY p.products_id
Demo here
Try this Code
SELECT p.products_id, pc.partner_channel, pc.active_status
FROM products p
LEFT JOIN products_catalog pc ON pc.products_id=p.products_id
WHERE pc.active_status='0'
GROUP BY p.products_id ORDER BY p.products_id DESC;
i try to list out all products with product images, but not sure how to use subquery in this situation. Below is my database structure
products
products_id + product_name +
1 | Apple |
2 | Banana |
products_screenshot
products_id + images +
1 | Apple-1.jpg |
1 | Apple-2.jpg |
1 | Apple-3.jpg |
2 | Banana-1.jpg |
2 | Banana-2.jpg |
2 | Banana-3.jpg |
this is my query:
$sql = "SELECT p.* FROM `products` p ORDER BY p.products_id ASC ";
//LEFT JOIN (SELECT ps.* FROM `products_screenshot` ps WHERE ps.products_id=p.products_id) AS pss ON(p.products_id=pss.products_id)
$query = $db->query($sql);
while ($row = $query->fetch_object()) {
// result
echo $row->products_name.'</br>';
// list all product screenshot related with this
//$row->images
}
With your requirement you can do as below. Then execute the query and loop through.
The
$row->images will be comma seperated and you can split them display them for a product.
$sql = "SELECT p.products_id,p.product_name,group_concat(pi.images) as `images`
FROM `products` p
left join products_screenshot pi on pi.products_id = p.products_id
group by p.products_id
ORDER BY p.products_id ";
If you dont care about products being repeated multiple times in the loop then just use below where for each loop you will get a new row with the product and the related images
$sql = "SELECT p.products_id,p.product_name,pi.images
FROM `products` p
left join products_screenshot pi on pi.products_id = p.products_id
ORDER BY p.products_id ";
What wrong with a simple query like this:
select
p.products_id,
p.product_name,
ps.images
from
products p
join products_screenshot ps
on p.products_id=ps.products_id
where
whateveryouline
order by
1,2
It will get you all the items you need?
Try this query:
select products.product_name, products_screenshot.images from products,products_screenshot where products.products_id = products_screenshot.products_id
SELECT * from products_screenshot as ps where products_id IN (SELECT p.products_id from products as p WHERE p.products_id = ps.products_id )
I'm trying to create a rating system, where the user can rate pictures/videos/audio etc. I have two tables at the moment
Table: products
Cols: product_id[PK] | name | category | type | link
This is the products table and contains information about the products. If you're confused by products, think of the "product" as the image/video/audio, I named it like this simply for allowing me to understand it easier. The second table is the ratings
Table: product_ratings
Cols: rating_id[PK] | rating | product_id | timestamp
This table stores information about the rating the user has given.
I want a page where it will display the highest rating (on average) for all "products". So far, I've looked through SA, and found the follow piece of code:
SELECT
p.product_id, p.name,
AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN product_ratings pr
ON pr.product_id = p.product_id
WHERE p.product_id = 1
This just returns the average rating for a specific product_id, How would I go about getting ALL the product_ids and their average rating, and how would I find the highest one via PHP?
I've tried:
WHERE p.product_id < 1 AND p.product_id < 30
But this just returns product_id of 2, with it's name and average_rating, which I don't understand.
Guidance/links to material are welcome
SELECT
p.product_id,
p.name,
AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN product_ratings pr
ON pr.product_id = p.product_id
GROUP BY p.product_id
ORDER BY rating_average DESC
LIMIT 1
Just try:
SELECT
p.product_id, p.name,
AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN product_ratings pr
ON pr.product_id = p.product_id
also this is meaningless expression:
WHERE p.product_id < 1 AND p.product_id < 30
because it is completely equivalent to
WHERE p.product_id < 1
and i doubt that you have ids below zero
Your query is close. Just remove the WHERE clause that filters everything.
SELECT p.product_id, p.name,
AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN product_ratings pr
ON pr.product_id = p.product_id
ORDER BY rating_average DESC
This will return you the averages for each product, sorted with the highest average rating at the top of the resultset.