2011-06-09 130 views
3

我不確定如何提出這個問題。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。

謝謝。

回答

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 

所以這個會發現(這允許在那兩個標籤與任何其他標記一起存在的情況下)

+0

這會在事件ID具有重複標記的情況下潛在地返回誤報 - 例如, (EventId,TagId)包含(1,1)和(1,1)。 – 2011-06-09 00:59:00

+0

我已經假設事件不會得到重複的標籤。我不認爲這是不合理的。我試圖想到一個重複標籤會有用的情況(考慮到問題中的信息) – Beno 2011-06-09 01:04:18

+0

標籤不會重複,因爲您在映射中對事件,標籤組合具有唯一約束。這是一個有趣的解決方案。 – nitefrog 2011-06-09 01:10:56

0

你要內部連接兩個表,如下

SELECT * FROM Events INNER JOIN MapTable ON MapTable.EventId=Events.EventID WHERE MapTable.TagID=1 AND MapTable.TagID=3

+0

這隻適用於一個標籤匹配,而不是兩個。 – 2011-06-09 00:56:29

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) 
+0

這是行不通的。他希望Events表中具有特定標籤的項目。 – 2011-06-09 00:47:24

+0

@DBM,完全誤解了它,認爲他只想從映射表中選擇,儘管我不知道爲什麼。已更新,可從事件表中選擇 – 2011-06-09 00:51:06

+0

@Jimmie不起作用。它仍然帶回只有一個選中的記錄。我只是在TSQL中運行它。它不會帶回具有所有選定標記的記錄。 – nitefrog 2011-06-09 00:58:46

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 
      ) 

僅返回所有標籤關聯的標籤。

再次感謝大家的想法!非常感謝所有的反饋!

+0

當「標籤」列表是動態的時,Beno的答案不起作用,即用戶可以使用UI來選擇它們,因爲您無法在包含聚合或子查詢的表達式上執行聚合函數。這就是說,你的代碼稍微有些偏離,因爲你還需要表變量@EventTags上的TagID,否則無論使用多少個標記,EventID都會有一個單獨的記錄。該更改修復了這個錯誤,並且按預期工作。 – 2015-08-10 22:34:33

相關問題