sql - SQL Server 2012 中的 LAST_VALUE 返回奇怪的结果

标签 sql sql-server sql-server-2012

当我尝试从 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 函数可能会返回奇怪的结果 - 见下文。

您可以使用 MAXLAST_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/

相关文章:

sql - 如何重建/重新安装 ssrs(reportserver、reportservertempdb)数据库?

mysql - 如何编写一个触发器,在提交插入之前更新同一个表中的行?

sql-server - X-max 的值必须大于 X-min 的值

sql-server - 根据两列动态旋转

sql - 根据日期删除一对值中的一个

sql-server - 寻找查询以在数据更改时返回数据值,否则返回空间 ' '

sql-server - 根据聚合创建大小均匀的组

java - 您如何将 Java 字符输入 MYSQL 数据库,然后再检索它们?

sql - 为什么在 WHERE 子句中使用 SQL 变量与使用相同值的常量会产生不同的结果?

sql - 如何将 SQL 中的主键更改为 auto_increment?