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)