2011-04-06 97 views
1

给出一个示例表'Users',它具有一个名为'UserID'的int列(以及一些其他任意数量的其他列),从UserID中选择所有行的最佳方式是什么不止一次出现?Tsql,返回具有相同列值的行

到目前为止,我已经拿出

select * from Users where UserID in 
(select UserID from Users group by UserID having COUNT(UserID) > 1) 

这似乎是一个相当innefficient的方式,虽然做到这一点,有没有更好的办法?

+2

不知道什么意思?你有数百万用户还是什么?我认为你的查询很好,如果您有数以百万计的行,那么当然UserID必须为此类查询编制索引。 – Arvo 2011-04-06 13:50:48

+0

我直觉地觉得必须有一些方法来做到这一点,而不使用子查询。当然,我可能完全错误。 – John 2011-04-06 13:54:03

+5

更重要的是:为什么userID'ever'会在Users表中多次出现? – 2011-04-06 14:01:01

回答

2

在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三种解决方案给出相同的计划。

0

这将做同样的事情,但评估的性能,它可能会更快/更有效。当然,这个UserID列应该有一个索引。

select u.* 
from Users u 
join (select UserID,count(UserID) as CUserID from Users group by UserID) u1 on u1.UserID = u.UserID 
where CUserID > 1 
相关问题