获取X个具有不同属性的最新条目SQL Server

时间:2016-07-06 12:39:40

标签: sql-server

我们说我有下表:

UserId | FileId | Version | Date
-------------------------------------
UserA  | FileA  | Version1| 1.1.2016
UserA  | FileA  | Version2| 2.1.2016
UserA  | FileA  | Version3| 2.1.2016
UserA  | FileA  | Version3| 3.1.2016
UserA  | FileA  | Version3| 4.1.2016
UserA  | FileA  | Version4| 5.1.2016
UserB  | FileA  | Version2| 3.1.2016

我想为4.1.2016之前创建的每个用户和文件获取最新的两个版本,因此结果应如下所示:

UserId | FileId | Version | Date
-------------------------------------
UserA  | FileA  | Version2| 2.1.2016
UserA  | FileA  | Version3| 3.1.2016    
UserB  | FileA  | Version2| 3.1.2016

获得此结果的正确SQL语句是什么?

目前,我正在尝试这样的事情

WITH FindNewestVersion AS
(
    SELECT DISTINCT 
        Date AS cDate, UserId AS UId, 
        FileId AS FId, Version AS Ver,   
        ROW_NUMBER() OVER (PARTITION BY UserId, FileId, Version ORDER BY Created DESC)rn 
    FROM 
        Table
    WHERE 
        Created <= [DATE]
)
SELECT * 
FROM Table AS q 
INNER JOIN (SELECT cDate, UId, FId, Ver 
            FROM FindNewestVersion 
            WHERE rn <= 2) AS x ON q.UserId = UId 
                                AND q.Date = cDate 
                                AND q.FileId = FId 
                                AND q.Version = Ver
GROUP BY q.UserId, q.FileId, q.Date, q.Version

但是这个陈述不太正确,因为它返回了这个结果

UserId | FileId | Version | Date
-------------------------------------
UserA  | FileA  | Version1| 1.1.2016
UserA  | FileA  | Version2| 2.1.2016
UserA  | FileA  | Version3| 2.1.2016
UserA  | FileA  | Version3| 3.1.2016    
UserB  | FileA  | Version2| 3.1.2016

所以,我不想要第一行(使用Version1)因为已经有两个其他更年轻的版本而且我不希望从2.1.2016开始使用Version3,因为有相同的条目来自3.1.2016更接近我输入的Date参数

2 个答案:

答案 0 :(得分:0)

尝试这样

注意:避免使用特定于文化的日期格式!

我使用CTE向该列添加一个列,该列按日期排序的每个UserId DESC编号。

注意2:我刚看到,一个用户可能有两个条目具有相同的日期。您可以将版本包含在OVER(... ORDER BY ...)

真实 SELECT为那些编号为1或2的

切割集合
SET LANGUAGE GERMAN;
DECLARE @tbl TABLE(UserId VARCHAR(100),FileId VARCHAR(100),Version VARCHAR(100),[Date] DATE);
INSERT INTO @tbl VALUES
 ('UserA','FileA','Version1','1.1.2016')
,('UserA','FileA','Version2','2.1.2016')
,('UserA','FileA','Version3','2.1.2016')
,('UserA','FileA','Version3','3.1.2016')
,('UserA','FileA','Version3','4.1.2016')
,('UserA','FileA','Version4','5.1.2016')
,('UserB','FileA','Version2','3.1.2016');

WITH Numbered AS
(
    SELECT ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY [Date] DESC) AS SortNr
          ,*
    FROM @tbl 
)
SELECT *
FROM Numbered
WHERE SortNr<=2

结果

1   UserA   FileA   Version4    2016-01-05
2   UserA   FileA   Version3    2016-01-04
1   UserB   FileA   Version2    2016-01-03

答案 1 :(得分:0)

试试这个,

CREATE TABLE #MyTable(UserId VARCHAR(50),FileId VARCHAR(50), [Version] VARCHAR(50),[Date] DATE);
INSERT INTO #MyTable 
VALUES
     ('UserA','FileA','Version1','1.1.2016')
    ,('UserA','FileA','Version2','2.1.2016')
    ,('UserA','FileA','Version3','2.1.2016')
    ,('UserA','FileA','Version3','3.1.2016')
    ,('UserA','FileA','Version3','4.1.2016')
    ,('UserA','FileA','Version4','5.1.2016')
    ,('UserB','FileA','Version2','3.1.2016')

;WITH CTE AS
(
    SELECT  *,
            ROW_NUMBER() OVER(PARTITION BY UserId,FileId,[Version] ORDER BY [Date] DESC) AS LatestVersion,
            DENSE_RANK() OVER(PARTITION BY UserId,FileId ORDER BY [Date] DESC ) AS VersionCount           
    FROM #MyTable 
    WHERE [Date] < '1-APR-2016'
)
SELECT *
FROM CTE
WHERE LatestVersion = 1
    AND VersionCount <= 2

它返回,

UserA   FileA   Version3    2016-03-01  1   1
UserA   FileA   Version2    2016-02-01  1   2
UserB   FileA   Version2    2016-03-01  1   1