TSQL查询所有记录必须存在以返回记录
我不确定如何提出这个问题。TSQL查询所有记录必须存在以返回记录
我的标签表:
TagId Tag
----- -----
1 Fruit
2 Meat
3 Grain
我有事件表:
EventId Event
------- -----------
1 Eating Food
2 Buying Food
,我需要做的是带回只有那些与它相关联的所有选定的标签活动。
如果选择了三个标签,则只显示包含全部三个标签的事件。
例如:
映射表
EventId TagId
------- -----
1 1
1 3
2 1
如果我写这样的查询:
select * from MapTable where where tagId in (1,3)
这将返回进食和购买食物。
但我需要做的是带回标签为1和3的事件。这意味着在这种情况下,我将返回的唯一事件就是“吃饭食物”,因为它同时包含所选标签。
我想知道这是否可以在TSQL中完成,或者如果我将不得不使用业务层将它翻译成对象返回到GUI。
谢谢。
昨天有个非常类似的问题:Query for exact match of users in a conversation in SQL Server
基本上你可以这样做:
DECLARE @NumTags INT = 2
SELECT EventID
FROM EventTag
GROUP BY EventID
HAVING
Sum(CASE WHEN TagID IN (1, 3) THEN 1 ELSE 0 END) >= @NumTags
所以这个会发现(这允许在那两个标签与任何其他标记一起存在的情况下)
你要内部连接两个表,如下
SELECT * FROM Events INNER JOIN MapTable ON MapTable.EventId=Events.EventID WHERE MapTable.TagID=1 AND MapTable.TagID=3
这只适用于一个标签匹配,而不是两个。 – 2011-06-09 00:56:29
有可能是一个更好的方式来写,但这会给你你在找什么:
select *
from event e
where exists(select * from maptable where eventid = e.eventid and tagid = 1) and exists(select * from maptable where eventid = e.eventid and tagid = 3)
这是行不通的。他希望Events表中具有特定标签的项目。 – 2011-06-09 00:47:24
@DBM,完全误解了它,认为他只想从映射表中选择,尽管我不知道为什么。已更新,可从事件表中选择 – 2011-06-09 00:51:06
@Jimmie不起作用。它仍然带回只有一个选中的记录。我只是在TSQL中运行它。它不会带回具有所有选定标记的记录。 – nitefrog 2011-06-09 00:58:46
这里是当你不知道该标签的解决方案都存在标签的所有事件之前。
装入标签到一个表变量,并获得总数:
select @iCount = COUNT(*) from @Tags;
然后写你的正常查询,这些结果撞到一个表变量:
insert into @EventTags(IsSet, EventId)
select distinct CASE WHEN TagID IN (select ID from @Tags) THEN 1 ELSE 0 END,
e.EventId
from Event_Tag e
inner join @Tags t on t.ID = e.TagId
然后回去只有全部匹配标签的事件,不仅仅是选中的标签,而是所有您需要做的事情:
select *
from Event_Tag e
inner join @Tags t on t.ID = e.TagId
where e.EventId in
( select EventId
from @EventTags
group by EventId
having count(EventId) = @iCount
)
仅返回所有标签关联的标签。
再次感谢大家的想法!非常感谢所有的反馈!
当“标签”列表是动态的时,Beno的答案不起作用,即用户可以使用UI来选择它们,因为您无法在包含聚合或子查询的表达式上执行聚合函数。这就是说,你的代码稍微有些偏离,因为你还需要表变量@EventTags上的TagID,否则无论使用多少个标记,EventID都会有一个单独的记录。该更改修复了这个错误,并且按预期工作。 – 2015-08-10 22:34:33
这会在事件ID具有重复标记的情况下潜在地返回误报 - 例如, (EventId,TagId)包含(1,1)和(1,1)。 – 2011-06-09 00:59:00
我已经假设事件不会得到重复的标签。我不认为这是不合理的。我试图想到一个重复标签会有用的情况(考虑到问题中的信息) – Beno 2011-06-09 01:04:18
标签不会重复,因为您在映射中对事件,标签组合具有唯一约束。这是一个有趣的解决方案。 – nitefrog 2011-06-09 01:10:56