SQL Server doesn't know or care about the order in which rows were inserted into the table. If you need specific order, always use ORDER BY
. In your example ORDER BY
is ambiguous, unless you include PK
into the ORDER BY
. Besides, LAST_VALUE
function can return odd results if you are not careful - see below.
You can get your expected result using MAX
or LAST_VALUE
(SQLFiddle). They are equivalent in this case:
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
Result of this query will be the same regardless of the order in which rows were originally inserted into the table. You can try to put INSERT
statements in different order in the fiddle. It doesn't affect the result.
Also, LAST_VALUE
behaves not quite as you'd intuitively expect with default window (when you have just ORDER BY
in the OVER
clause). Default window is ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
, while you'd expected it to be ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
. Here is a SO answer with a good explanation. The link to this SO answer is on MSDN page for LAST_VALUE
. So, once the row window is specified explicitly in the query it returns what is needed.
If you want to know the order in which rows were inserted into the table, I think, the most simple way is to use IDENTITY
. So, definition of your table would change to this:
CREATE TABLE Data
(PK INT IDENTITY(1,1) PRIMARY KEY,
Id1 INT,
Id2 INT)
When you INSERT
into this table you don't need to specify the value for PK
, the server would generate it automatically. It guarantees that generated values are unique and growing (with positive increment parameter), even if you have many clients inserting into the table at the same time simultaneously. There may be gaps between generated values, but the relative order of the generated values will tell you which row was inserted after which row.