按两列SQL Server

时间:2017-07-03 16:59:44

标签: sql sql-server-2012

我有一个跟踪版本历史记录的表。我想只获取最新版本以及表中每个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

4 个答案:

答案 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]

为此,我需要一个额外的联接,但我想知道是否可以不附加联接。