SQL Server - Wählen Sie die neuesten Datensätze aus einer Gruppe von ähnlichen Datensätzen
-- Scrollen Sie nach unten für ein edit, dass ich Hinzugefügt --
So, hier ist mein Szenario. Ich habe eine Tabelle mit einem Eintrag für jedes mal, wenn jemand eine änderung um einige Daten. Der Grund dafür ist, dass wir brauchen, um in der Lage sein zu überprüfen, die änderungen.
Jedoch möchte ich nur abrufen, den aktuellen Datensatz für eine Reihe von Bearbeitungen ein Benutzer gemacht hat.
Also lasst uns sagen, es gibt drei Benutzer A, B und C.
Benutzer A 10 änderungen (10 Einträge in der Tabelle).
User B macht 5 änderungen
User A macht 3 mehr verpasst
User C macht 2 änderungen
Was ich will zurück zu bekommen ist:
Letzten 2 Datensätze C erstellt
Jüngste von den 3 Datensätzen, die Eine erstellt
Jüngste der 5 Datensätze, die B erstellt
Letzte 10 Datensätze, die Eine erstellt
Insgesamt 4 Zeilen, die ich wieder
Hier ist, was ich versucht, aber das problem ist, dass die RowNum nicht wieder zurück auf 1, wenn die LastUpdatedBy änderungen:
WITH cte AS
(
SELECT
[LastUpdatedOn]
,[LastUpdatedBy]
,ROW_NUMBER() OVER(PARTITION BY [LastUpdatedBy] ORDER BY [LastUpdatedOn] DESC) [RowNum]
FROM [HistoricalTable]
)
SELECT
[LastUpdatedOn]
,[LastUpdatedBy]
,RowNum
FROM cte
--WHERE RowNum = 1
ORDER BY [LastUpdatedOn] DESC;
Und hier ist die Ausgabe die ich bekomme (** Sternchen stehen für die Zeilen, ich will wieder)
LastUpdatedOn LastUpdatedBy RowNum
**2011-06-07 13:07:26.917 629 1**
2011-06-07 12:57:53.700 629 2
2011-06-07 12:57:44.387 629 3
2011-06-07 12:57:34.913 629 4
2011-06-07 12:57:25.040 629 5
2011-06-07 12:57:19.927 629 6
2011-06-07 12:55:17.460 629 7
2011-06-07 12:55:12.287 629 8
2011-06-07 12:30:34.377 629 9
**2011-06-07 11:54:05.727 4 1**
**2011-06-07 11:50:02.723 629 10** (If this number went back to 1, my query would have worked fine)
2011-06-07 11:26:43.053 629 11
2011-06-07 10:54:32.867 629 12
2011-06-07 10:46:32.107 629 13
2011-06-07 10:40:52.937 629 14
**2011-06-07 10:39:50.880 3 1**
------------------- BEARBEITEN --------------------
Also ich kam mit einer Lösung, aber es ist nicht sehr elegant und nicht sicher, ob ich es mag, aber es funktioniert der trick. Dies könnte Ihnen ein besseres Verständnis von dem, was ich versuche zu erreichen.
DECLARE @temp AS TABLE(LastUpdatedOn datetime, LastUpdatedBy int null, RowNum int);
DECLARE @newTable AS TABLE(LastUpdatedOn datetime, LastUpdatedBy int null);
DECLARE @lastUserId int = 0;
INSERT INTO @temp
SELECT
[LastUpdatedOn]
,[LastUpdatedBy]
,ROW_NUMBER() OVER(ORDER BY [LastUpdatedOn] DESC) [RowNum]
FROM [HistoricalTable]
DECLARE @totalRecords int;
SELECT @totalRecords = COUNT(*) FROM @temp;
DECLARE @counter int = 0;
WHILE @counter <= @totalRecords BEGIN
SET @counter = @counter + 1;
INSERT INTO @newTable
SELECT LastUpdatedOn, LastUpdatedBy
FROM @temp
WHERE RowNum = @counter AND (@lastUserId != LastUpdatedBy OR (LastUpdatedBy IS NULL));
SELECT @lastUserId = LastUpdatedBy FROM @temp WHERE RowNum = @counter;
END
SELECT * FROM @newTable;
Sowie die Daten, die zurückgegeben wird:
LastUpdatedOn LastUpdatedBy
2011-06-07 13:07:26.917 629
2011-06-07 11:54:05.727 4
2011-06-07 11:50:02.723 629
2011-06-07 10:39:50.880 3
- Diese Abfrage(mit WHERE RowNum = 1 auskommentiert) sollte in der Tat geben Sie das gewünschte Ergebnis...da sind Sie, die Teilung des Ergebnisses durch den Benutzer setzen und bestellen dann den Datensatz basierend auf dem Datum, das Sie bekommen sollten, wird der oberste Datensatz aktualisiert von jedem Benutzer, wenn Sie das filtern der Datensätze nach RowNum = 1. Können Sie das bestätigen wieder einmal?
- In deinem Beispiel A macht 10 änderungen und dann A macht 3 weitere änderungen. Ihr code wird zurückgegeben, der letzten änderung, die Einer gemacht hat. Aber Ihre Frage sagt, du willst zwei Zeilen, für die änderungen. Was unterscheidet den ersten Satz der änderungen aus dem zweiten?
- Ja, es wäre das filtern der Datensätze aus, wenn ich kommentieren, aber nicht ganz korrekt. Wenn Sie sehen, meine Daten Ausgang sehen Sie, wo es geht von Benutzer 629 zu 4 Benutzer, dann auf 629 wieder. Wo geht es zu 629 wieder, RowNum geht um 10 statt 1, und dann werde ich nicht diese Platte, die ich brauche.
- Wenn Sie einen Blick auf die Ausgabe der Daten, werden Sie feststellen, dass 4 Benutzer (oder Benutzer B. Benutzer-IDS von der DB anstelle von A,B,C) eine änderung vorgenommen, die zwischen allen Benutzer 629 ' s verpasst. Aus diesem Grund würde separate Benutzer-629 änderungen in zwei Sätzen.
- Seit der Bestellung von LastUpdatedBy, sollten Sie nie finden Sie in der Ausgabe, die Sie eingefügt haben. Die Daten müssen zuerst partitioniert LastUpdatedBy und dann durch LastUpdatedOn. Also alle die 629 Datensätze shd werden zusammen gruppiert und dann sortiert.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Erstellen Sie eine Zeilennummer für jede Zeile eine Reihenfolge von
LastUpdatedOn
- und Fügeverfahren in die nächste Zeile und vergleichen, wenn LastUpdatedBy geändert wird.Hüten Sie sich vor dieser
coalesce(C2.LastUpdatedBy, 0)
. Es ist, um die Letzte Zeile und die0
werden müssen, einige integer-Wert nicht verwendet werden, daLastUpdatedBy
.Nicht sicher, ob ich etwas fehlt in Ihrer Frage, aber nicht die folgenden SQL-Antwort das problem ?
Fiel es mir heute morgen, dass diese Inseln ein problem. Hier ist meine Lösung:
Den "trick" hier ist zu beachten, dass, wenn Sie verfolgen die row_number sowohl innerhalb einer partition und für den ganzen Satz, der Unterschied zwischen den beiden wird sich ändern, wenn die partition ändern.
Dies ist völlig ungetestet, aber es könnte die basis für eine funktionierende Lösung:
Selbst wenn dieser Ansatz funktioniert, die performance wird wohl schrecklich sein, vorausgesetzt, Sie haben mehr als nur eine Handvoll Zeilen.
Für jede Zeile in der Tabelle stellt sicher, dass es nicht existiert, jede andere Zeile(N) durch denselben Benutzer, der zwischen der Kontext-Zeile und die älteste Zeile, die Aktueller ist als die Kontext-Zeile verknüpft mit einem anderen Benutzer.