Ответ 1
Термин для этого типа проблемы реляционное разделение. Один из способов ниже.
SELECT PageID
FROM pagetags
WHERE TagID IN ( 1, 2, 4 )
GROUP BY PageID
HAVING Count(DISTINCT TagID) = 3
Как выбрать только те элементы, которые он хочет в списке IN? например
select * from pagetags where TagID in (1,2,4)
Теперь я хочу, чтобы все страницы, у которых есть все перечисленные выше 3 идентификатора (1,2,4), а не только любой из них, но все они?
Есть ли способ? любого другого оператора? Я уже пробовал = Any
и = All
, но не повезло.
Термин для этого типа проблемы реляционное разделение. Один из способов ниже.
SELECT PageID
FROM pagetags
WHERE TagID IN ( 1, 2, 4 )
GROUP BY PageID
HAVING Count(DISTINCT TagID) = 3
вы можете попробовать что-то вроде этого:
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
Выбранный ответ Мартина Смита
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 объединений оптимизатор запросов часто будет принимать некоторые плохие решения.
И с этим не использовали Группу, если вам это нужно для другой агрегации.
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