2017-07-03 1 views
0

Ich habe eine Tabelle, die Versionsgeschichte verfolgt. Ich möchte nur die neueste Version zusammen mit dem Datum für jede ID in der Tabelle abrufen. Das folgende gibt mir das späteste Datum für jede ID, Versionskombination. Wie kann ich nur den obersten Rekord auswählen? Ich kann dies in einer temporären Tabelle speichern und dann Join verwenden, um nur den obersten Datensatz für jede ID, Versionskombination zu erhalten. Gibt es einen besseren Weg, dies in einem einzigen Schritt zu erreichen?Erhalten Sie den neuesten Datensatz, wenn nach zwei Spalten gruppiert SQL Server

Beispieldaten

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 

Erwartete Ausgabe

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 

Abfrage

select id,version,max(dt_create) 
from version_history (nolock) 
group by id,version 
order by id 

Ich habe dies versucht, aber ich habe das gleiche Ergebnis wie oben

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 

Antwort

0

Die zweite Abfrage ich Werke verwenden, nachdem ich von der Partition Klausel entfernen Version haben

select * from 
( 
    select id,version,dt_create,row_number() over (partition by id order by dt_create desc) as a 
    from version_history (nolock) 
) b 
where a=1 
order by id 
1

können Sie die Klausel WITH TIES

Beispiel

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) 

Returns

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 
+0

Thanks.My Tabelle hat 210 Millionen Aufzeichnungen und das dauert 40+ Minuten. Mit Join bekomme ich die Ergebnisse in 8 Minuten zurück. –

+0

@inquisitive_mind Happy Sie haben eine Lösung. Ich kann mir nicht vorstellen, warum du mehr als 40 Minuten hast, wenn du deine Daten nicht in die Tabellenvariable geladen hast. –

1

Ich sehe, Sie konnten dies durch Partitionierung erreichen, aber ich möchte Ihnen einen anderen Ansatz zeigen. Sie können die Leistung für sich selbst vergleichen und sehen, was am schnellsten ist - (ich gehe davon aus, dass die Partitionierung besser ist).

Zuerst wissen wir, dass es sogar für die neueste Version mehrere Daten geben kann, also wollen Sie nicht die maximale Version für jede ID, sondern Sie wollen das maximale Datum!

Zuerst das Setup:

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') 

Nun, um jede ID mit dem max Datum zu erhalten:

SELECT ID, 
     MAX([TimeStamp]) AS MaxTimeStamp 
FROM @table 
GROUP BY ID 

Dies gibt uns, was wir wollen:

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) 

Jetzt sind wir muss nur die Version enthalten. Das sollte einfach sein, weil wir eine Selbstverknüpfung auf ID und Datum können:

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] 

Und das gibt uns die folgenden Ergebnisse:

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) 

Bitte beachte, dass wir unsere ursprüngliche Anfrage an die beitreten gleiche Tabelle - nach ID und Datum, wie besprochen.Allerdings sind wir jetzt eine zusätzliche Spalte, Version auszuwählen, so muss es alternativ in der GROUP BY

aufgenommen werden, können Sie die gleichen Ergebnisse erzielen, indem CROSS APPLY mit:

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] 
Verwandte Themen