具有多对多关系的MySQL限制

具有多对多关系的MySQL限制,mysql,database,tags,tagging,Mysql,Database,Tags,Tagging,给出了实现标记的模式 项目 ItemId,ItemContent 标签 标记名 物品标签 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子句会出现问题,因为您

给出了实现标记的模式

项目 ItemId,ItemContent

标签 标记名

物品标签 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中的行数。

可能类似于

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

我的第一个建议是使用子查询生成项目ID的列表,并返回与这些项目ID匹配的项目。但这不包括结果集中的标记名。我将提交另一个解决方案的单独答案

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引擎应该将其分解并只运行一次。

我的第二个解决方案使用MySQL函数组_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的一部分。

您也可以使用Distinct/GROUP By:


选择DISTINCT TagID,TagName FROM((标记T
内部联接项(T.TagID=I\u T.TagID上的标记I\u T)
I_T.ItemID=I.ItemID)上的内部联接项I)
按标记ID、标记名分组