如何在 IN 列表中只选择他想要的项目?例如
select * from pagetags where TagID in (1,2,4)
现在我想要所有分配了以上 3 个 ID 的页面(1,2,4),不只是其中任何一个,而是全部?
有办法吗?任何其他运营商?我已经尝试过= Any
,= All
但没有运气。
如何在 IN 列表中只选择他想要的项目?例如
select * from pagetags where TagID in (1,2,4)
现在我想要所有分配了以上 3 个 ID 的页面(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 倍的性能提升。
从具有 300 万行的表中返回 272 的查询需要 0.2 秒和 2.0 秒。
还在具有 5 个标签和相同 10 倍但现在为 0.5 与 5.0 的更大表上进行了测试。
索引是PageID,TagID 有百万个PageID 和数百个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 个连接,查询优化器通常会做出一些错误的决定。
如果您需要将它用于另一个聚合,那么它还没有用完 Group By。
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