0

Мои знания SQL действительно немного ржавые, но у меня есть несколько простой вопрос для экспертов. У меня есть три таблицы:Самый эффективный способ конкат-строк

сообщения - POST_ID - имя - описание

posts_categories - post_id - слизняк

posts_themes - post_id - слизняк

В основном я хотел бы для запроса списка сообщений, например:

SELECT post_id, name, description, themes, categories FROM posts LIMIT 0, 50 

Я хотел бы объединить соответствующие категории таблиц темы и объединить их в один столбец. Таким образом мой выход будет:

1 | тестирование | описание | музыка, искусство, история | важный, актуальный, новый

Я попытался использовать это как подзапрос, но попал в общую проблему, когда было возвращено несколько строк. Я также попытался ПОЛНОСТЬЮ ПРИСОЕДИНИТЬ результаты, но я не могу получить правильные результаты. Из-за боязни подслушивать мои результаты, не осознавая этого, я надеялся, что кто-то может помочь сформулировать наиболее эффективный и правильный запрос.

Спасибо.

ответ

1

Начиная с вашего основного стола (сообщений), вы можете делать регулярные соединения с таблицами тем и категорий. Левые соединения используются в этом случае, чтобы разрешить строки, которые не имеют категории или темы, которые будут отображаться в результате.

Чтобы получить значения, разделенные запятыми, вы группируете значения из posts (те, которые должны иметь одно значение для каждой строки) и использовать GROUP_CONCAT() для запятой разделить негруппированные значения, что-то вроде;

SELECT p.post_id, p.name, p.description, 
    COALESCE(GROUP_CONCAT(pc.slug), '') categories, 
    COALESCE(GROUP_CONCAT(pt.slug), '') themes 
FROM posts p 
LEFT JOIN posts_categories pc ON p.post_id = pc.post_id 
LEFT JOIN posts_themes pt ON p.post_id = pt.post_id 
GROUP BY p.post_id, p.name, p.description 
ORDER BY p.post_id, p.name, p.description 
LIMIT 50 

An SQLfiddle to test with.

+0

Мне нравится ваше решение больше, чем Олли Джоун, однако я не знаю, почему это необходимо для группировки по имени и описанию. Также я получаю дублирующие результаты в своем наборе данных. Как я могу гарантировать, что они уникальны? Я считаю, что бросать DISTINCT() до того, как GROUP_CONCAT будет работать. – ddibiase

+0

@ddibiase В MySQL вы можете группировать только по id в том случае, если идентификатор достаточно уникален, однако другие RDBMS (postgresql/sql server/oracle/...) или даже некоторые режимы MySQL могут быть установлены на более строгие и требуют от вас для группировки по всем одиночным значениям. Я не уверен, какие дубликаты вы получаете, не могли бы вы добавить пример? –

+0

Ничего, он закончил работать. Благодаря! – ddibiase

0

Вы являетесь будущим довольным клиентом GROUP_CONCAT().

Рассмотрим этот подзапрос:

SELECT post_id, GROUP_CONCAT(slug) AS slugs 
    FROM posts_categories 
GROUP BY post_id 

Это даст вам разделенный запятыми список категорий слизней по почте. Аналогичный запрос даст вам темы.

Затем вы просто присоединяетесь к этим подзапросам, получая это.

SELECT a.post_id, a.name, a.description, 
     b.slugs AS categories, 
     c.slugs AS themes 
    FROM posts AS a 
    LEFT JOIN (
      SELECT post_id, GROUP_CONCAT(slug) AS slugs 
      FROM posts_categories 
      GROUP BY post_id 
     ) AS b ON a.post_id = b.post_id 
    LEFT JOIN (
      SELECT post_id, GROUP_CONCAT(slug) AS slugs 
      FROM posts_themes 
      GROUP BY post_id 
     ) AS c ON a.post_id = c.post_id 
ORDER BY a.post_id 

Хитрость заключается в том, чтобы создать правильные сводки в виде подзапросов, а затем присоединить их к таблице столбов.

Примечание: если вы работаете только с категориями или только с темами, вы можете избежать подзапроса, просто LEFT JOIN в таблице posts_categories и выполнить GROUP BY по основному запросу. Но если вы присоединитесь к столам post_categories и posts_themes, вы получите комбинаторный взрыв и множество дополнительных данных в списках, разделенных запятой.