2012-09-24 32 views
15

如何才能在IN列表中只选择他想要的项目?例如如何选择项目匹配仅在SQL服务器中的IN列表

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

现在我希望所有的页面拥有所有分配给他们(1,2,4)上述3点的ID,不是任何人,但所有的人?

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

回答

22

这种类型的问题是relational division。下面的一种方法。

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

好的,我应该写我的原始模式,因为这比上面的例子更困难:)但你救了我,谢谢你。 – Ali

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 
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,带有数百万PageID和数百个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 

身高去年一样,拥有超过500联接查询优化器经常会做出一些错误的决定。
而这还没有用完分组依据,如果你需要它的另一个聚合。

+0

它取决于可用的索引和系统中标签的数量。基本上和比较['PIVOT' vs'JOIN']一样(http://stackoverflow.com/questions/7448453/sql-server-pivot-vs-multiple-join/7449213#7449213)。如果要查看的标记数量是可变的,则除非通过动态SQL生成查询,否则这不是非常可扩展的。 –

+0

@MartinSmith在我的情况下,索引是PageID TagID。少于1000个TagID,但可以拥有数百万个PageID。由程序使用。所以我很乐意参加10倍的表现。 – Paparazzi

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 
+3

一些解释可能会有所帮助! –

相关问题