开发者

TSQL Query Where All Records Must Exists to Return A Record

I am not sure even how to ask this question.

I have a table of tags:

TagId  Tag
-----  -----
1      Fruit
2      Meat
3      Grain

I have a table of events:

EventId   Event
-------   -----------
1         Eating开发者_如何学编程 Food
2         Buying Food

What I need to do is bring back only Events that have all selected tags associated with it.

If three tags are selected then only show event that have all three.

For example:

Mapping Table

EventId   TagId
-------   -----
1         1
1         3
2         1

If I write a query like this:

select * from MapTable where where tagId in (1,3)

This will return Eating Food and Buying Food.

But what I need to do is bring back events that have both tags 1 and 3. This means that the only event in this case I would return would be Eating Food as it has both selected tags.

I was wondering if this can be done in TSQL or if I will have to use the business layer to translate it into the object to return back to the GUI.

Thanks.


There was a very similar question yesterday: Query for exact match of users in a conversation in SQL Server

basically you can do this:

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

so this will find all events that both the tags exist in (this allows for instances where those two tags exist along with any additional tags)


Here is a solution for when you do not know the tags before hand.

Load the tags into a table variable and get the total count:

select @iCount = COUNT(*) from @Tags;

Then write your normal query and slam those results into a table variable:

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

Then to get back only Events that have ALL matching tags, not just ones that are in the selection, but ALL you do this:

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
              )

Only bring back tags that have all tags associated.

Thank you again everyone for the ideas! Greatly appreciated all the feedback!


There's probably a better way to write it but this will give you what you are looking for:

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)


You'll want to inner join the two tables, as follows

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜