Obtenir X quantité de dernières inputs avec différents attributes SQL Server

Disons que j'ai le tableau suivant:

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 

Et je veux get les deux dernières versions pour chaque user et file qui ont été créés avant le 4.1.2016, donc le résultat devrait ressembler à ceci:

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

Quelle serait l'instruction SQL correcte pour get ce résultat?

En ce moment, j'essaie quelque chose comme ça

 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 

Mais cette affirmation n'est pas tout à fait correcte, car elle renvoie ce résultat

 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 

Donc, je ne veux pas la première ligne (avec Version1) car il y a déjà deux autres versions plus jeunes et je ne veux pas l'input avec Version3 du 2.1.2016 car il y a la même input du 3.1.2016 qui est plus proche de mon paramètre Date entré

Essayez comme ça

Attention: Évitez les formats de date spécifiques à la culture!

J'utilise un CTE pour append une colonne à l'set qui est numérotée pour chaque DESC UserId sortingé par la date.

Attention2: Je viens de voir, qu'un user peut avoir deux inputs avec la même date. Vous pourriez inclure la version à la fin OVER(... ORDER BY ...)

Le vrai SELECT coupe l'set pour ceux qui sont numérotés avec 1 ou 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 

Le résultat

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

essaye ça,

 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 

Ça revient,

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