SQL Server neví nebo se nezajímá o pořadí, ve kterém byly řádky vloženy do tabulky. Pokud potřebujete konkrétní objednávku, vždy použijte ORDER BY
. Ve vašem příkladu ORDER BY
je nejednoznačné, pokud nezahrnete PK
do ORDER BY
. Kromě toho LAST_VALUE
funkce může vrátit liché výsledky, pokud si nedáte pozor - viz níže.
Očekávaný výsledek můžete získat pomocí MAX
nebo LAST_VALUE
(SQLFiddle
). V tomto případě jsou ekvivalentní:
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
Výsledek tohoto dotazu bude stejný bez ohledu na pořadí, ve kterém byly řádky původně vloženy do tabulky. Můžete zkusit vložit INSERT
výroky v různém pořadí v houslích. Nemá to vliv na výsledek.
Také LAST_VALUE
se nechová úplně tak, jak byste intuitivně očekávali s výchozím oknem (když máte jen ORDER BY
v OVER
doložka). Výchozí okno je ŘÁDKY MEZI NEOZEŽENÝM PŘEDCHOZÍM A AKTUÁLNÍM ŘÁDKEM
, zatímco jste očekávali, že se bude jednat o ŘÁDY MEZI BEZ ODPOVĚDNOSTI PŘEDCHÁZEJÍCÍ A BEZ OMEZENÍ NÁSLEDUJÍCÍ
. Zde je odpověď SO s dobré vysvětlení
. Odkaz na tuto odpověď SO je na stránce MSDN pro LAST_VALUE
. Jakmile je tedy řádkové okno v dotazu explicitně specifikováno, vrátí to, co je potřeba.
Pokud chcete vědět, v jakém pořadí byly řádky vloženy do tabulky, myslím, že nejjednodušším způsobem je použít IDENTITA
. Definice vaší tabulky by se tedy změnila na toto:
CREATE TABLE Data
(PK INT IDENTITY(1,1) PRIMARY KEY,
Id1 INT,
Id2 INT)
Když INSERT
do této tabulky nemusíte zadávat hodnotu pro PK
, server by jej vygeneroval automaticky. Zaručuje, že generované hodnoty jsou jedinečné a rostoucí (s kladným parametrem přírůstku), i když do tabulky vkládáte mnoho klientů současně. Mezi vygenerovanými hodnotami mohou být mezery, ale relativní pořadí vygenerovaných hodnot vám řekne, který řádek byl vložen za který řádek.