TSQL-запрос, где все записи должны существовать, чтобы вернуть запись - PullRequest
3 голосов
/ 09 июня 2011

Я даже не знаю, как задать этот вопрос.

У меня есть таблица тегов:

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.

Спасибо.

Ответы [ 4 ]

4 голосов
/ 09 июня 2011

Вчера был очень похожий вопрос: Запрос на точное совпадение пользователей в разговоре в 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 голос
/ 10 июня 2011

Вот решение для случаев, когда вы не знаете теги заранее.

Загрузите теги в табличную переменную и получите общее количество:

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 голосов
/ 09 июня 2011

Возможно, есть лучший способ написать это, но это даст вам то, что вы ищете:

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 голосов
/ 09 июня 2011

Вы захотите объединить две таблицы следующим образом:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...