Как выбрать элемент соответствия Только IN List в sql server

Как выбрать только те элементы, которые он хочет в списке IN? например

select * from pagetags where TagID in (1,2,4)

Теперь я хочу, чтобы все страницы, у которых есть все перечисленные выше 3 идентификатора (1,2,4), а не только любой из них, но все они?

Есть ли способ? любого другого оператора? Я уже пробовал = Any и = All, но не повезло.

Ответы

Ответ 1

Термин для этого типа проблемы реляционное разделение. Один из способов ниже.

SELECT PageID
FROM   pagetags
WHERE  TagID IN ( 1, 2, 4 )
GROUP  BY PageID
HAVING Count(DISTINCT TagID) = 3

Ответ 2

вы можете попробовать что-то вроде этого:

SELECT id, Tag FROM (
SELECT id, Tag, COUNT(*) OVER(partition by id) as cnt
FROM pagetags
WHERE Tag in(1,2,4)
GROUP BY id, tag
) a WHERE a.cnt = 3

Ответ 3

Выбранный ответ Мартина Смита

SELECT PageID
FROM   pagetags
WHERE  TagID IN ( 1, 2, 4 )
GROUP  BY PageID
HAVING Count(DISTINCT TagID) = 3

является правильным, но если скорость является проблемой, попробуйте это.

У меня есть большая таблица, делающая то же самое и получившая 10-кратную лучшую производительность со следующим. 0,2 секунды против 2,0 секунд для запроса, возвращающего 272 из таблицы с 3 миллионами строк.
Также тестировали на большом столе с 5 тегами и одинаковыми 10x, но теперь 0,5 против 5.0.
Индекс - это идентификатор страницы, TagID с миллионами идентификаторов страниц и сотни TagID.
Общий сценарий, в котором много объектов отмечены многозначным свойством.

    SELECT distinct(p1.PageID)
    FROM   pagetags p1
    JOIN   pagetags p2
      ON   p2.PageID = p1.PageID
      AND  p2.TagID = 2 
    JOIN   pagetags p3
      ON   p3.PageID = p1.PageID
      AND  p3.TagID = 4
    WHERE  p1.PageID = 1
 ORDER BY  p1.PageID

или

   SELECT  distinct(PageID)
    FROM   pagetags
    WHERE  TagID = 1
   INTERSECT
   SELECT  distinct(PageID)
    FROM   pagetags
    WHERE  TagID = 2 
   INTERSECT
   SELECT  distinct(PageID)
    FROM   pagetags
    WHERE  TagID = 4 
 ORDER BY  PageID

Предпочитайте последнее, так как более 5 объединений оптимизатор запросов часто будет принимать некоторые плохие решения.
И с этим не использовали Группу, если вам это нужно для другой агрегации.

Ответ 4

SELECT distinct(PageID)
FROM   pagetags
WHERE  TagID IN (1,2,4)
and PageID in
(select distinct(PageID) from pagetags group by PageID having count(TagID)=3)
group by PageID