Sql 查找具有两个或多个关系的行
我有三张桌子:Sql 查找具有两个或多个关系的行,sql,sql-server,Sql,Sql Server,我有三张桌子: Foodstable存储所有食品,Tagstable存储所有标签,FoodTagRelation存储食品和标签之间的关系。我想写一个查询来选择所有正好有两个标签且ID为的食物(请阅读我在底部写的SQL) 现在我想选择所有有两个标签的食物:例如,选择所有有两个标签的食物:水果和冷的 select * from Foods inner join FoodTagRelation on Foods.Id=FoodTagRelation.FoodId where tagid in
Foods
table存储所有食品,Tags
table存储所有标签,FoodTagRelation
存储食品和标签之间的关系。我想写一个查询来选择所有正好有两个标签且ID为的食物(请阅读我在底部写的SQL)
现在我想选择所有有两个标签的食物:例如,选择所有有两个标签的食物:水果和冷的
select * from Foods
inner join FoodTagRelation
on
Foods.Id=FoodTagRelation.FoodId
where
tagid in ('1','2')
我尝试了这个查询,但它返回了所有带有标签水果
或冷
的食物
select * from Foods
inner join FoodTagRelation
on
Foods.Id=FoodTagRelation.FoodId
where
tagid in ('1','2')
如何重新编写此查询以仅返回同时具有标签的食品
SELECT * from Foods where FoodId in (
select FoodID from FoodTagRelation where TagId in (1,2)
group by FoodId having count(*)=2
)
注意更新我的SQL,因为Rusi似乎只关心TagId为(1或2)的带有精确to标签的食品在FoodID上分组,并使用having count(TagId)=2
功能:使用count distinct,以防止FoodTagration表中给定FoodID出现重复标记ID的问题。(如果您不认为重复是一个问题,那么您可以删除'distinct'关键字)。其次,我保留了WHERE子句,因为它允许您查找特定的标记,而不是任何两个标记。最后,我列出了您的字段,因为这是使用group by子句所必需的(而group by子句又是使用HAVING子句所必需的)。当您说“选择所有食物,精确地选择2个标签”,如果一种食物有3个标签,其中包括水果和冷藏以及其他标签。算数吗
不管怎样,这里有一个查询,可以找到既有水果又有冷的食物
SELECT *
FROM Foods f
INNER JOIN FoodTagRelation ft1
ON f.Id=ft1.FoodId
INNER JOIN FoodTagRelation ft2
ON f.Id=ft2.FoodId
WHERE
ft1.tagid = 1 AND ft2.tagid = 2
有关允许您更改正在搜索的标签的更一般的答案:
DECLARE @Search_Tags TABLE (TagId INT)
INSERT INTO @Search_Tags (TagId) VALUES (1), (2)
SELECT
F.Id,
F.FoodItem
FROM
Foods F
INNER JOIN FoodTagRelation FTR ON
FTR.FoodId = F.Id
INNER JOIN @Search_Tags ST ON
ST.TagId = FTR.TagId
GROUP BY
F.Id,
F.FoodItem
HAVING
COUNT(*) = (SELECT COUNT(*) FROM @Search_Tags)
我对这个问题进行了编辑,使其内容更加翔实。由于您在('1','2')
中遗漏了子句tagid,请查看我在底部编写的sql。@Rusi Nova:更新了我的答案。现在,对于标签1或标签2,你只会得到正好有2个标签的食物。我已经对这个问题进行了编辑,使其更具信息性。由于('1','2')
中缺少了子句tagid,请查看我在底部编写的sql。@Rusi。。我添加了附加条件。您将发现,对于几个值,使用or子句而不是in子句可能会获得更好的性能。
SELECT *
FROM Foods f
INNER JOIN FoodTagRelation ft1
ON f.Id=ft1.FoodId
INNER JOIN FoodTagRelation ft2
ON f.Id=ft2.FoodId
WHERE
ft1.tagid = 1 AND ft2.tagid = 2
DECLARE @Search_Tags TABLE (TagId INT)
INSERT INTO @Search_Tags (TagId) VALUES (1), (2)
SELECT
F.Id,
F.FoodItem
FROM
Foods F
INNER JOIN FoodTagRelation FTR ON
FTR.FoodId = F.Id
INNER JOIN @Search_Tags ST ON
ST.TagId = FTR.TagId
GROUP BY
F.Id,
F.FoodItem
HAVING
COUNT(*) = (SELECT COUNT(*) FROM @Search_Tags)