当我尝试从 SQL Server 2012 中的表中获取 LAST_VALUE 时,出现了奇怪的结果。
这是我的 table
PK | Id1 | Id2
1 | 2 | 5
2 | 2 | 6
3 | 2 | 5
4 | 2 | 6
这是我的查询
SELECT
Id1, Id2, LAST_VALUE(PK) OVER (PARTITION BY Id1 ORDER BY Id2) AS LastValue
FROM
@Data
这就是我期待的结果
Id1 | Id2 | LastValue
2 | 5 | 3
2 | 5 | 3
2 | 6 | 4
2 | 6 | 4
这就是我收到的内容
Id1 | Id2 | LastValue
2 | 5 | 3
2 | 5 | 3
2 | 6 | 2
2 | 6 | 2
这是问题的演示
http://sqlfiddle.com/#!6/5c729/1
我的查询有什么问题吗?
最佳答案
SQL Server 不知道也不关心行插入表中的顺序。如果您需要特定顺序,请始终使用 ORDER BY
。在您的示例中,ORDER BY
是不明确的,除非您将 PK
包含到 ORDER BY
中。此外,如果您不小心,LAST_VALUE
函数可能会返回奇怪的结果 - 见下文。
您可以使用 MAX
或 LAST_VALUE
( SQLFiddle ) 获得预期结果。在这种情况下它们是等效的:
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
无论行最初插入表中的顺序如何,此查询的结果都将相同。您可以尝试在 fiddle 中以不同的顺序放置 INSERT
语句。不影响结果。
此外,LAST_VALUE
的行为并不完全符合您对默认窗口的直观预期(当您在 OVER
子句中只有 ORDER BY
时) )。默认窗口是 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
,而您希望它是 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
。这是一个带有 good explanation 的答案。此答案的链接位于 MSDN 页面上的 LAST_VALUE
。因此,一旦在查询中显式指定行窗口,它就会返回所需的内容。
如果你想知道行插入表的顺序,我认为最简单的方法是使用 IDENTITY
。因此,您的表的定义将更改为:
CREATE TABLE Data
(PK INT IDENTITY(1,1) PRIMARY KEY,
Id1 INT,
Id2 INT)
当您INSERT
到该表中时,您不需要指定PK
的值,服务器会自动生成它。它保证生成的值是唯一的并且不断增长(具有正增量参数),即使您有许多客户端同时插入表中也是如此。生成的值之间可能存在间隙,但生成的值的相对顺序将告诉您哪一行插入到哪一行之后。
关于sql - SQL Server 2012 中的 LAST_VALUE 返回奇怪的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29971151/