21

如何在 IN 列表中只选择他想要的项目?例如

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

现在我想要所有分配了以上 3 个 ID 的页面(1,2,4),不只是其中任何一个,而是全部?

有办法吗?任何其他运营商?我已经尝试过= Any= All但没有运气。

4

4 回答 4

32

这类问题的术语是关系划分。下面的一种方式。

SELECT PageID
FROM   pagetags
WHERE  TagID IN ( 1, 2, 4 )
GROUP  BY PageID
HAVING Count(DISTINCT TagID) = 3
于 2012-09-24T11:21:19.667 回答
0

你可以尝试这样的事情:

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
于 2012-09-24T11:35:56.083 回答
0

马丁史密斯的精选答案

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。

于 2012-09-24T12:24:57.730 回答
0
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
于 2014-01-06T11:02:37.437 回答