2010-10-28 3 views
1

У меня есть две таблицы.mysql group_concat

продукты

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 

Почему не первая работа запроса при его спрашивает то же самое, что и второй запрос, и как я могу заставить его работать.

ответ

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 является без sargable. Это потребует полного сканирования таблицы на 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 
+0

Что не-sargable среднего – andrew

+0

(Из википедии). В реляционных базах данных условие (или предикат) в запросе считается способным, если механизм СУБД может использовать индекс для ускорения выполнения запроса (используя индексные запросы, а не индексы). Этот термин получен из сокращения Search ARGument Able. –

+0

Это отлично поработало. – andrew