我有两张桌子。
产品
id title image_ids
---------------------
1 myproduct 1,2,3
图片
id title file_name
-------------------------
1 myimage myimage.jpg
2 myimage2 myimage2.jpg
3 myimage3 myimage3.jpg
我想查询,以便将图像的名称连接到每个产品参考的单个字段中。
此查询不起作用
SELECT products.title,
products.image_ids,
GROUP_CONCAT(images.file_name)
FROM products
LEFT JOIN images ON images.id IN (products.image_ids)
WHERE products.id = 1
GROUP BY products.id
这个确实:
SELECT products.title,
products.image_ids,
GROUP_CONCAT(images.file_name)
FROM products
LEFT JOIN images ON images.id IN (1,2,3)
WHERE products.id = 1
GROUP BY products.id
并产生预期的结果
title image_ids file_names
--------------------------------------------------------------
myproduct 1,2,3 myimage.jpg,myimage2.jpg,myimage3.jpg
为什么第一个查询在询问与第二个查询相同的内容时是否有效,以及如何使其工作。
答案 0 :(得分:2)
IN
不适用于以逗号分隔的值列表。
基本上,你不是在比较整数,而是在比较字符串:
SELECT 1 IN (1, 2, 3) -- True
SELECT 1 IN ('1, 2, 3') -- False ('1' <> '1, 2, 3')
改为使用FIND_IN_SET
:
SELECT products.title,products.image_ids, GROUP_CONCAT(images.file_name)
FROM products
LEFT JOIN
images
ON FIND_IN_SET(images.id, products.image_ids)
WHERE products.id = 1
GROUP BY
products.id
然而,由于FIND_IN_SET
不可攻击,因此这不是性能方面的最佳解决方案。它需要images
上的全表扫描。
如果您对products.image_ids
中的值数量有一些合理限制(例如,每个产品不超过5
张图片),则可以改为使用此查询:
SELECT products.title,products.image_ids, GROUP_CONCAT(images.file_name)
FROM (
SELECT 1 AS n
UNION ALL
SELECT 2 AS n
UNION ALL
SELECT 3 AS n
UNION ALL
SELECT 4 AS n
UNION ALL
SELECT 5 AS n
) q
CROSS JOIN
products
LEFT JOIN
images
ON SUBSTRING_INDEX(SUBSTRING_INDEX(image_ids, ',', n), ',', 1)
WHERE products.id = 1
AND SUBSTRING_INDEX(image_ids, ',', n) <> SUBSTRING_INDEX(image_ids, ',', n - 1)
GROUP BY
products.id