Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

LAST_VALUE in SQL Server 2012 gibt seltsame Ergebnisse zurück

SQL Server kennt oder kümmert sich nicht um die Reihenfolge, in der Zeilen in die Tabelle eingefügt wurden. Wenn Sie eine bestimmte Reihenfolge benötigen, verwenden Sie immer ORDER BY . In Ihrem Beispiel ORDER BY ist mehrdeutig, es sei denn, Sie fügen PK ein in das Feld ORDER BY . Außerdem LAST_VALUE -Funktion kann ungerade Ergebnisse zurückgeben, wenn Sie nicht aufpassen - siehe unten.

Sie können Ihr erwartetes Ergebnis mit MAX erhalten oder LAST_VALUE (SQLFiddle ). Sie sind in diesem Fall äquivalent:

SELECT
    PK, Id1, Id2
    ,MAX(PK) OVER (PARTITION BY Id1, Id2) AS MaxValue
    ,LAST_VALUE(PK) OVER (PARTITION BY Id1, Id2 ORDER BY PK rows between unbounded preceding and unbounded following) AS LastValue
FROM
    Data
ORDER BY id1, id2, PK

Das Ergebnis dieser Abfrage ist unabhängig von der Reihenfolge, in der die Zeilen ursprünglich in die Tabelle eingefügt wurden, dasselbe. Sie können versuchen, INSERT einzufügen Aussagen in unterschiedlicher Reihenfolge in der Geige. Das Ergebnis wird dadurch nicht beeinflusst.

Außerdem LAST_VALUE verhält sich nicht ganz so, wie Sie es intuitiv mit dem Standardfenster erwarten würden (wenn Sie nur ORDER BY haben im OVER Klausel). Das Standardfenster ist ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW , obwohl Sie erwartet hatten, dass es sich um ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING handelt . Hier ist eine SO-Antwort mit einem gute Erklärung . Der Link zu dieser SO-Antwort befindet sich auf der MSDN-Seite für LAST_VALUE . Sobald also das Zeilenfenster explizit in der Abfrage angegeben ist, gibt es zurück, was benötigt wird.

Wenn Sie wissen möchten, in welcher Reihenfolge Zeilen in die Tabelle eingefügt wurden, ist es meiner Meinung nach am einfachsten, IDENTITY . Die Definition Ihrer Tabelle würde sich also wie folgt ändern:

CREATE TABLE Data 
(PK INT IDENTITY(1,1) PRIMARY KEY,
Id1 INT,
Id2 INT)

Wenn Sie INSERT In dieser Tabelle müssen Sie den Wert für PK nicht angeben , würde der Server es automatisch generieren. Es garantiert, dass die generierten Werte eindeutig sind und wachsen (mit positivem Inkrementparameter), selbst wenn Sie viele Clients gleichzeitig in die Tabelle einfügen. Es kann Lücken zwischen den generierten Werten geben, aber die relative Reihenfolge der generierten Werte zeigt Ihnen, welche Zeile nach welcher Zeile eingefügt wurde.