MySQL Limit с отношениями многие ко многим - PullRequest
2 голосов
/ 03 октября 2008

С учетом схемы для реализации тегов

ITEM ItemId, ItemContent

TAG TagId, TagName

ITEM_TAG ItemId, TagId

Каков наилучший способ ограничения количества пунктов, возвращаемых при выборе с помощью тегов?

SELECT i.ItemContent, t.TagName FROM item i 
INNER JOIN ItemTag it ON i.id = it.ItemId 
INNER JOIN tag t ON t.id = it.TagId 

, конечно, самый простой способ вернуть их всех, но использование предложения limit не работает, потому что вы получаете дубликат всех элементов для каждого тега, который учитывается в количестве строк в LIMIT.

Ответы [ 4 ]

5 голосов
/ 03 октября 2008

Мое второе решение использует функцию MySQL GROUP_CONCAT () для объединения всех тегов, соответствующих элементу, в строку с разделителями-запятыми в наборе результатов.

SELECT i.ItemContent, GROUP_CONCAT(t.TagName ORDER BY t.TagName) AS TagList
FROM item AS i 
  INNER JOIN ItemTag AS it ON i.id = it.ItemId 
  INNER JOIN tag AS t ON t.id = it.TagId
GROUP BY i.ItemId;

Функция GROUP_CONCAT () является функцией MySQL, она не является частью стандартного SQL.

1 голос
/ 03 октября 2008

Может быть, что-то вроде

select i.ItemContent, t.TagName from (SELECT ItemId, ItemContent FROM item limit 10) i
INNER JOIN ItemTag it ON i.ItemId = it.ItemId --You will miss tagless items here!
INNER JOIN tag t ON t.id = it.TagId
0 голосов
/ 03 октября 2008

Вы также можете использовать Distinct / Group By:

SELECT DISTINCT TagID, TagName FROM ((TAG T INNER JOIN ITEM_TAG I_T ON T.TagID = I_T.TagID) INNER JOIN ITEM I ON I_T.ItemID = I.ItemID) GROUP BY TagID, TagName

0 голосов
/ 03 октября 2008

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

SELECT i.ItemContent
FROM item AS i
WHERE i.id IN (
  SELECT it.ItemId
  FROM ItemTag AS it
    INNER JOIN tag AS t ON (t.id = it.TagId)
  WHERE t.TagName IN ('mysql', 'database', 'tags', 'tagging')
);

Это некоррелированный подзапрос, поэтому хороший движок SQL должен его разложить и запустить только один раз.

...