Как получить список с отношением 1: N - PullRequest
3 голосов
/ 30 мая 2011

У меня есть таблица «статей», и у меня есть таблица «тегов».Между ними есть отношение N: N, поэтому у меня тоже есть таблица «article_tags_relations».Я хотел бы получить список статей с тегами, однако в дополнение к названию тега мне также нужен его идентификатор.Таким образом, возвращаемые данные должны быть примерно такими (конечно, не в формате JSON):

[[1,"FirstArticle",{"1":"FirstTag","2":"SecondTag"}],[2,"SecondArticle",{"3":"ThirdTag"}]]

Пока у меня есть что-то вроде:

SELECT article.*, GROUP_CONCAT(tag.name SEPARATOR ', ') AS tags FROM articles AS article LEFT JOIN articles_tags_relations AS relation ON article.id = relation.article_id LEFT JOIN tags AS tag ON relation.tag_id = tag.id LIMIT 0,10;

Но в нем есть только имена тегов безидентификаторыВ таблице будет много запросов на чтение, поэтому производительность важна.Я не уверен, что использование GROUP_CONCAT - путь, я открыт для любых идей.Спасибо!

Ответы [ 4 ]

1 голос
/ 30 мая 2011

Насколько я знаю, GROUP_CONCAT() работает вместе с предложением GROUB BY. Однако есть два варианта получения tag.id с вашими данными:

SELECT article.*, tag.id AS tags_id, GROUP_CONCAT(tag.name SEPARATOR ', ') AS tags FROM articles AS article LEFT JOIN articles_tags_relations AS relation ON article.id = relation.article_id LEFT JOIN tags AS tag ON relation.tag_id = tag.id LIMIT 0,10;

А 2:

SELECT article.*, GROUP_CONCAT(tag.name SEPARATOR ', ') AS tags, GROUP_CONCAT(tag.id SEPARATOR ', ') AS tag_ids FROM articles AS article LEFT JOIN articles_tags_relations AS relation ON article.id = relation.article_id LEFT JOIN tags AS tag ON relation.tag_id = tag.id LIMIT 0,10;
1 голос
/ 30 мая 2011

Вы должны сделать это в одном запросе? Я бы сделал один запрос, чтобы получить статьи, а затем второй, чтобы получить теги для этих идентификаторов статей. Я не уверен, как производительность сравнивается, хотя. (И это, вероятно, зависит от скорости вашей сети относительно стоимости второго запроса по сравнению с левым соединением.)

Тем не менее, попытка объединить несколько фрагментов данных в SQL-запросе кажется, что это идет вразрез с духом реляционной базы данных и с меньшей вероятностью будет работать так же хорошо, как и база данных.

0 голосов
/ 30 мая 2011

Вы почти у цели.Добавьте CONCAT, чтобы получить идентификатор и запись вместе, или создайте отдельное предложение GROUP_CONCAT для каждого.

SELECT article.*, 
  GROUP_CONCAT(CONCAT(tag.id,':',tag.name)) AS tags 
FROM articles AS article 
LEFT JOIN articles_tags_relations AS relation ON article.id = relation.article_id 
LEFT JOIN tags AS tag ON relation.tag_id = tag.id
GROUP BY article.id 
LIMIT 0,10

AFAIK. В GROUP_CONCAT нет ничего особенного, что приведет к снижению производительности.


Просто для интереса приведем запрос, который вернет JSON

SELECT CONCAT('[',GROUP_CONCAT(CONCAT('[',row_data,']')),']') as JSON
FROM
(
  SELECT CONCAT(a.id,',"',a.title,'",{',GROUP_CONCAT(CONCAT("'",tag.id,'":"',tag.name,'"')),'}') as row_data
  FROM articles AS a 
  LEFT JOIN articles_tags_relations AS relation ON a.id = relation.article_id 
  LEFT JOIN tags AS tag ON relation.tag_id = tag.id
  GROUP BY a.id 
  LIMIT 0,10 
) t1
0 голосов
/ 30 мая 2011

Извините, похоже, я не понимаю вашу проблему.Для меня решения просты: select a.id, a.name, t.id, t.name from articles a, tags t, articles_tags_relations atr where a.id = atr.article_id and t.id = atr.tag_id

Конечно, это не форматирует результат так, как вы хотите, но форматирование - это не то, для чего предназначен SQL.Сначала вы получаете результат (см. Выше), а затем используете язык программирования по вашему выбору для форматирования набора результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...