2011-04-06 39 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 
相關問題