【问题标题】:MySQL Limit with Many to Many RelationshipMySQL 限制多对多关系
【发布时间】:2008-10-03 14:12:38
【问题描述】:
给定一个用于实现标签的 SCHEMA
项目
项目 ID、项目内容
标签
标记ID、标记名称
ITEM_TAG
ItemId, TagId
使用标签选择时限制返回的ITEMS数量的最佳方法是什么?
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 中的行数。
【问题讨论】:
标签:
mysql
database
tags
tagging
【解决方案1】:
我的第二个解决方案使用 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 的一部分。
【解决方案2】:
可能是这样的
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
【解决方案3】:
我的第一个建议是使用子查询来生成项目 ID 列表并返回与这些项目 ID 匹配的项目。但这不包括结果集中的 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 引擎应该把它分解出来并且只运行一次。
【解决方案4】:
你也可以使用 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