如何才能在IN列表中只选择他想要的项目?例如如何选择项目匹配仅在SQL服务器中的IN列表
select * from pagetags where TagID in (1,2,4)
现在我希望所有的页面拥有所有分配给他们(1,2,4)上述3点的ID,不是任何人,但所有的人?
有没有办法?任何其他运营商?我已经尝试过= Any
和= All
,但没有运气。
如何才能在IN列表中只选择他想要的项目?例如如何选择项目匹配仅在SQL服务器中的IN列表
select * from pagetags where TagID in (1,2,4)
现在我希望所有的页面拥有所有分配给他们(1,2,4)上述3点的ID,不是任何人,但所有的人?
有没有办法?任何其他运营商?我已经尝试过= Any
和= All
,但没有运气。
这种类型的问题是relational division。下面的一种方法。
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,带有数百万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联接查询优化器经常会做出一些错误的决定。
而这还没有用完分组依据,如果你需要它的另一个聚合。
它取决于可用的索引和系统中标签的数量。基本上和比较['PIVOT' vs'JOIN']一样(http://stackoverflow.com/questions/7448453/sql-server-pivot-vs-multiple-join/7449213#7449213)。如果要查看的标记数量是可变的,则除非通过动态SQL生成查询,否则这不是非常可扩展的。 –
@MartinSmith在我的情况下,索引是PageID TagID。少于1000个TagID,但可以拥有数百万个PageID。由程序使用。所以我很乐意参加10倍的表现。 – Paparazzi
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
一些解释可能会有所帮助! –
好的,我应该写我的原始模式,因为这比上面的例子更困难:)但你救了我,谢谢你。 – Ali