我甚至不确定如何提出这个问题。
我有一张标签表:
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的事件。这意味着在这种情况下我将返回的唯一事件是Eating Food,因为它有两个选定的标签。
我想知道这是否可以在TSQL中完成,或者我是否必须使用业务层将其转换为对象以返回GUI。
感谢。
答案 0 :(得分:4)
昨天有一个非常相似的问题: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
所以这将找到两个标签都存在的所有事件(这允许这两个标签与任何其他标签一起存在的实例)
答案 1 :(得分:1)
这是一个解决方案,供您在事先知道标签时使用。
将标记加载到表变量中并获取总计数:
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
)
仅返回包含所有标记的标记。
再次感谢大家的想法!非常感谢所有的反馈!
答案 2 :(得分:0)
您需要内连接两个表,如下所示
SELECT * FROM Events INNER JOIN MapTable ON MapTable.EventId=Events.EventID WHERE MapTable.TagID=1 AND MapTable.TagID=3
答案 3 :(得分:0)
可能有更好的方式来编写它,但这会给你你想要的东西:
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)