我有一个跟踪版本历史记录的表。我想只获取最新版本以及表中每个id的日期。 下面将给出每个id,版本组合的最新日期。如何才能选择最高记录?我可以将它存储在临时表中,然后使用join来获取每个id,版本组合的最高记录。是否有更好的方法可以在一个步骤中完成此操作?
示例数据
id version timestamp
123 1.5 2015-03-28 08:21:04.563
123 1.0 2015-03-21 12:58:24.730
234 1.5 2016-10-15 23:08:09.550
345 1.5 2016-05-10 15:18:09.707
345 1.5 2016-09-02 21:30:00.657
预期输出
id version timestamp
123 1.5 2015-03-28 08:21:04.563
234 1.5 2016-10-15 23:08:09.550
345 1.5 2016-09-02 21:30:00.657
查询
select id,version,max(dt_create)
from version_history (nolock)
group by id,version
order by id
我试过这个,但我得到的结果与上面相同
select * from
(
select id,version,dt_create,row_number() over (partition by id,version order by dt_create desc) as a
from version_history (nolock)
) b
where a=1
order by id
答案 0 :(得分:1)
您可以使用WITH TIES子句
示例强>
Declare @YourTable Table ([id] int,[version] varchar(50),[timestamp] datetime)
Insert Into @YourTable Values
(123,1.5,'2015-03-28 08:21:04.563')
,(123,1.0,'2015-03-21 12:58:24.730')
,(234,1.5,'2016-10-15 23:08:09.550')
,(345,1.5,'2016-05-10 15:18:09.707')
,(345,1.5,'2016-09-02 21:30:00.657')
Select Top 1 with ties *
From @YourTable
Order By Row_Number() over (Partition By ID Order By timestamp Desc)
<强>返回强>
id version timestamp
123 1.5 2015-03-28 08:21:04.563
234 1.5 2016-10-15 23:08:09.550
345 1.5 2016-09-02 21:30:00.657
答案 1 :(得分:1)
我看到你能够通过分区实现这一目标,但是我想向您展示另一种方法。您可以自己比较性能并查看最快的 - (我假设分区更好)。
首先,我们知道即使是最新版本也可能有多个日期,所以你真的不想要每个id的最大版本,而是你想要最大日期!
首先,设置:
DECLARE @table TABLE (ID INT, [Version] DECIMAL(18, 2), [TimeStamp] DATETIME)
INSERT INTO @table
VALUES
(123, 1.5, '2015-03-28 08:21:04.563'),
(123, 1.5, '2015-03-21 12:58:24.730'),
(234, 1.5, '2016-10-15 23:08:09.550'),
(345, 1.5, '2016-05-10 15:18:09.707'),
(345, 1.5, '2016-09-02 21:30:00.657')
现在,要获取每个ID的最大日期:
SELECT ID,
MAX([TimeStamp]) AS MaxTimeStamp
FROM @table
GROUP BY ID
这给了我们想要的东西:
ID MaxTimeStamp
----------- -----------------------
123 2015-03-28 08:21:04.563
234 2016-10-15 23:08:09.550
345 2016-09-02 21:30:00.657
(3 row(s) affected)
现在我们只需要包含该版本。这应该很简单,因为我们可以在ID和日期进行自我加入:
SELECT T.ID,
MAX(T.[TimeStamp]) AS [MaxTimeStamp],
T2.[Version] AS [MaxVersion]
FROM @table T
JOIN @table T2
ON T.ID = T2.ID
AND T.[TimeStamp] = T2.[TimeStamp]
GROUP BY T.ID, T2.[Version]
这给了我们以下结果:
ID MaxTimeStamp MaxVersion
----------- ----------------------- ---------------------------------------
123 2015-03-28 08:21:04.563 1.50
234 2016-10-15 23:08:09.550 1.50
345 2016-09-02 21:30:00.657 1.50
(3 row(s) affected)
请注意,我们将原始查询加入到同一个表中 - 按ID和日期,如上所述。但是,我们现在正在选择其他列Version,因此需要将其包含在GROUP BY
或者,您可以使用CROSS APPLY
:
SELECT T.ID,
MAX(T.[TimeStamp]) AS MaxTimeStamp,
T2.[Version]
FROM @table T
CROSS APPLY
(
SELECT Version
FROM @table T2
WHERE T2.ID = T.ID
AND T2.[TimeStamp] = T.[TimeStamp]
) T2
GROUP BY T.ID, T2.[Version]
答案 2 :(得分:0)
我从分区子句
中删除版本后,我的第二个查询有效{{1}}
答案 3 :(得分:0)
以上所有答案并没有真正选择2列中的最新列。最长时间戳只有1列。
如果以前的版本可以将更高版本的构建日期(例如,安全错误修复)作为更高版本,则设置可能是这样的:
DECLARE @table TABLE (ID INT, [Version] DECIMAL(18, 2), [TimeStamp] DATETIME)
INSERT INTO @table
VALUES
(123,1.5,'2015-03-28 08:21:04.563')
,(123,1.0,'2015-03-21 12:58:24.730')
,(123,1.0,'2016-03-21 12:58:24.730') --new
,(234,1.5,'2016-10-15 23:08:09.550')
,(345,1.5,'2016-05-10 15:18:09.707')
,(345,1.5,'2016-09-02 21:30:00.657')
随后,较早的答案将得到4条记录,其中包括带有2016年日期的1.0版ID 123。 如果那不是意图,那么这将是解决方案:
SELECT T.ID,
MAX(T.[TimeStamp]) AS [MaxTimeStamp],
T3.[Version] AS [MaxVersion]
FROM @table T
JOIN (
SELECT T4.ID,
MAX(T4.[Version]) AS [MaxVersion]
FROM @table T4
GROUP BY T4.ID
) as T2 ON T.id = T2.id
JOIN @table T3
ON T.ID = T3.ID
--AND T2.ID = T3.ID --works fine somehow with or without thise line
AND T.[TimeStamp] = T3.[TimeStamp]
AND T3.[Version] = T2.[MaxVersion]
GROUP BY T.ID, T3.[Version]
为此,我需要一个额外的联接,但我想知道是否可以不附加联接。