I have two tables: products(id)
and product_images(id, parent_id, src, is_default)
Each product has n
images.
I want to get all products and one image for each of them.
If the column is_default
is 1( BOOL
), then get that image, otherwise get the first one.
My query looks like this
SELECT
main.*,
images.id image_id, images.src image_src
FROM products main
LEFT JOIN product_images images ON main.id = images.parent_id AND images.is_default = 1
GROUP BY main.id
ORDER BY main.id DESC
Obviously the JOIN
condition is not right and I can't figure it out.
Hope you can help,
Thank you.
I suppose that the first image is the one with the lowest ID, I would start with this query:
SELECT
parent_id,
COALESCE(
MIN(CASE WHEN is_default=1 THEN ID END),
MIN(id)
) AS image_id
FROM product_images
GROUP BY parent_id
this will return the image where is_default = 1, if there's no default MIN(case when...) will be null and then COALESCE will select just MIN(id). Then you can join your query with the previous subquery:
SELECT main.*, images.id image_id, images.src image_src
FROM
products main LEFT JOIN JOIN (
SELECT
parent_id,
COALESCE(
MIN(CASE WHEN is_default=1 THEN ID END),
MIN(id)
) AS min_image_id
FROM product_images
GROUP BY parent_id
) fi ON fi.parent_id = main.id
LEFT JOIN product_images images
ON images.id = fi.min_image_id
Using GROUP_CONCAT.
This gets all the image details for each main ordered by is_default descending, and then by id. So if there are no records with is_default set to 1 then it will get the first image first. Then uses SUBSTRING_INDEX to get the first details.
Note that if images.src can contain a comma you might want to use a different delimiter.
SELECT
main.*,
SUBSTRING_INDEX(GROUP_CONCAT(images.id ORDER BY images.is_default DESC, images.id), ',', 1) AS image_id,
SUBSTRING_INDEX(GROUP_CONCAT(images.src ORDER BY images.is_default DESC, images.id), ',', 1) AS image_src
FROM products main
LEFT JOIN product_images images ON main.id = images.parent_id
GROUP BY main.id
ORDER BY main.id DESC
You can grab the single image information in a subquery:
SELECT main.*,
(SELECT images.id
FROM product_images image
WHERE main.id = images.parent_id
AND images.is_default = 1
ORDER BY images.id
) image_id,
(SELECT images.src
FROM product_images image
WHERE main.id = images.parent_id
AND images.is_default = 1
ORDER BY images.id
) image_src
FROM products main
You will need a sub-query. I think this is the simplest solution.
SELECT
*
FROM (
SELECT main.*, images.id image_id, images.src image_src
FROM products as main
LEFT JOIN product_images as images ON main.id = images.parent_id
ORDER BY images.is_default DESC
) as t
GROUP BY t.id
This does what you want, but orders by the images.is_default desc, so that if the is_default is 1, then this will show at the top. The outer query GROUP BY
will force the one with the is_default to be selected if is_default
is set.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.