[英]Select the top 1 row from each group
我有一個表,列出了已安裝的軟件版本:
id | userid | version | datetime
----+--------+---------+------------------------
111 | 75 | 10075 | 2013-03-12 13:40:58.770
112 | 75 | 10079 | 2013-03-12 13:41:01.583
113 | 78 | 10065 | 2013-03-12 14:18:24.463
114 | 78 | 10079 | 2013-03-12 14:22:20.437
115 | 78 | 10079 | 2013-03-12 14:24:01.830
116 | 78 | 10080 | 2013-03-12 14:24:06.893
117 | 74 | 10080 | 2013-03-12 15:31:42.797
118 | 75 | 10079 | 2013-03-13 07:03:56.157
119 | 75 | 10080 | 2013-03-13 07:05:23.137
120 | 65 | 10080 | 2013-03-13 07:24:33.323
121 | 68 | 10080 | 2013-03-13 08:03:24.247
122 | 71 | 10080 | 2013-03-13 08:20:16.173
123 | 78 | 10080 | 2013-03-13 08:28:25.487
124 | 56 | 10080 | 2013-03-13 08:49:44.503
我想顯示每個userid
的一條記錄的所有字段,但只顯示最高版本(版本也是varchar
)。
如果使用SQL-Server(最低2005),則可以使用帶有ROW_NUMBER
函數的CTE
。 您可以使用CAST
版本來獲取正確的順序:
WITH cte
AS (SELECT id,
userid,
version,
datetime,
Row_number()
OVER (
partition BY userid
ORDER BY Cast(version AS INT) DESC) rn
FROM [dbo].[table])
SELECT id,
userid,
version,
datetime
FROM cte
WHERE rn = 1
ORDER BY userid
即使有多個用戶具有相同(頂部)版本, ROW_NUMBER
始終返回一條記錄。 如果要返回所有“頂級版本用戶記錄”,則必須用DENSE_RANK
替換ROW_NUMBER
。
您沒有指定如何處理關系,但如果您希望顯示重復項,則會執行此操作;
SELECT a.* FROM MyTable a
LEFT JOIN MyTable b
ON a.userid=b.userid
AND CAST(a.version AS INT) < CAST(b.version AS INT)
WHERE b.version IS NULL
如果你想消除重復項,如果它們存在,請選擇最新的副本,你將不得不稍微擴展一下;
WITH cte AS (SELECT *, CAST(version AS INT) num_version FROM MyTable)
SELECT a.id, a.userid, a.version, a.datetime
FROM cte a LEFT JOIN cte b
ON a.userid=b.userid
AND (a.num_version < b.num_version OR
(a.num_version = b.num_version AND a.[datetime]<b.[datetime]))
WHERE b.version IS NULL
WITH records
AS
(
SELECT id, userid, version, datetime,
ROW_NUMBER() OVER (PARTITION BY userID
ORDER BY version DESC) rn
FROM tableName
)
SELECT id, userid, version, datetime
FROM records
WHERE RN =1
select l.* from the_table l
left outer join the_table r
on l.userid = r.userid and l.version < r.version
where r.version is null
我認為這可以解決您的問題:
SELECT id,
userid,
Version,
datetime FROM (
SELECT id,
userid,
Version,
datetime ,
DENSE_Rank() over (Partition BY id order by datetime asc) AS Rankk
FROM [dbo].[table]) RS
WHERE Rankk<2
我根據你的要求使用了RANK功能....
以下代碼將顯示您想要的內容並且非常適合性能!
select * from the_table t where cast([version] as int) =
(select max(cast([version] as int)) from the_table where userid = t.userid)
如果我的經驗調整教會了我什么,那么普遍性就是糟糕的壞事。
但是,如果獲得Top X
的表格很大(即數十萬或數百萬)。 CROSS APPLY
幾乎是普遍最好的。 事實上,如果你的基准它,跨應用在較小的規模始終與令人欽佩執行,以及(在幾萬)和不斷覆蓋與領帶潛在需求。
就像是:
select
id
,userid
,version
,datetime
from
TheTable t
cross apply
(
select top 1 --with ties
id
from
TheTable
where
userid = t.userid
order by
datetime desc
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.