Получение тегов для контента из второй таблицы в одном sql - PullRequest
1 голос
/ 05 декабря 2011

У меня есть две таблицы, одна для сообщений, одна для тегов, связанных с сообщениями, где posts.tags содержит идентификаторы тегов, связанных с сообщением.

Сообщения:

id | title  | tags
-----------------
 1 | Foobar | 1 3 7
 2 | Barfoo | 2 3 7

теги:

id | tag
--------
 1 | Tag1
 2 | Tag2
... and so forth

При запросе к сообщению я хотел бы получить сообщение со всеми его тегами в виде разделенной пробелами строки вместо идентификатора тега.

Я пробовал запрос как:

SELECT *, 
(
  SELECT GROUP_CONCAT(tags.tag)
  FROM tags 
  WHERE tags.id LIKE 1 OR tags.id LIKE 3
) AS tag_str
FROM posts

Это в основном выводит то, что я ищу; То, что я не могу понять, это правильное условие WHERE в подпункте, которое проверяет, по моим собственным словам, «для тегов WHERE tag.id соответствует любой разделенной пробелами числовой строке в posts.tags» - если есть такой запрос возможно?

Любая помощь приветствуется, к.

1 Ответ

3 голосов
/ 05 декабря 2011

Ваш фундаментальный дизайн базы данных несовершенен, и теперь вы страдаете от последствий этого недостатка.Если у вас есть возможность исправить это, вы должны это сделать.Теги не должны храниться в виде строки, разделенной пробелами, в одном столбце таблицы Posts.Вместо этого у вас должна быть соединительная таблица Posts_Tags_xref, которая бы разрешала отношение «многие ко многим».Эта таблица будет состоять из двух внешних ключей, Posts.id и Tags.id.

enter image description here

. Для приведенных выше примеров данных вы должны иметь:

Posts_Tags_xref
==================
post_id     tag_id
-------     ------
      1          1
      1          3
      1          7
      2          2
      2          3
      2          7

И запрос, который вы запрашиваете, становится:

SELECT p.post_id, p.title, GROUP_CONCAT(t.tag)
    FROM Posts p
        LEFT JOIN Posts_Tags_xref ptx
            INNER JOIN Tags t
                ON ptx.tag_id = t.tag_id
            ON p.post_id = ptx.post_id
    GROUP BY p.post_id, p.title;
...