在SQL Server 2005 +,你可以使用这种方法:
;WITH UsersNumbered AS (
SELECT
UserID,
rownum = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UserID)
FROM Users
)
SELECT u.*
FROM Users u
INNER JOIN UsersNumbered n ON u.UserID = n.UserID AND n.rownum = 2
只要存在于UserID
一个非聚集索引,这会产生比你的方法略差执行计划。为了使其更好(实际上,你的一样),你需要使用...一个子查询,但反直觉的,它可能看起来:
;WITH UsersNumbered AS (
SELECT
UserID,
rownum = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UserID)
FROM Users
)
SELECT u.*
FROM Users u
WHERE EXISTS (
SELECT *
FROM UsersNumbered n
WHERE u.UserID = n.UserID AND n.rownum = 2
);
在一个聚集索引的情况下,对所有UserID
三种解决方案给出相同的计划。
不知道什么意思?你有数百万用户还是什么?我认为你的查询很好,如果您有数以百万计的行,那么当然UserID必须为此类查询编制索引。 – Arvo 2011-04-06 13:50:48
我直觉地觉得必须有一些方法来做到这一点,而不使用子查询。当然,我可能完全错误。 – John 2011-04-06 13:54:03
更重要的是:为什么userID'ever'会在Users表中多次出现? – 2011-04-06 14:01:01