SQL Server 2012中的最后一个值返回奇怪的结果

SQL Server 2012中的最后一个值返回奇怪的结果,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,当我试图从SQLServer2012中的表中获取最后一个_值时,我得到了一个奇怪的结果 这是我的桌子 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 |

当我试图从SQLServer2012中的表中获取最后一个_值时,我得到了一个奇怪的结果

这是我的桌子

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
下面是问题的一个例子

我的问题有什么不对吗

依赖底层数据库引擎的特定实现所导致的隐式顺序从来都不是一个好主意

我不知道为什么,运行查询

SELECT * FROM @Data ORDER BY Id2
结果将是

+----+-----+-----+
| PK | id1 | id2 |
+----+-----+-----+
|  1 |   2 |   5 |
|  3 |   2 |   5 |
|  4 |   2 |   6 |
|  2 |   2 |   6 |
+----+-----+-----+
这意味着SQL Server以不同于插入顺序的方式决定行的顺序

这就是为什么LAST_值行为与预期不同,但与SQL Server排序方法一致的原因

但是SQL Server如何对数据进行排序呢


我们得到的最佳答案是我在答案开头的句子中接受的答案。

SQL Server不知道或不关心将行插入表中的顺序。如果您需要特定的订单,请始终使用order BY。在您的示例中,ORDER BY是不明确的,除非您将PK包括在ORDER BY中。此外,如果您不小心,LAST_VALUE函数可能会返回奇数结果-请参见下文

您可以使用MAX或LAST_值获得预期结果。在这种情况下,它们是等效的:

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
无论行最初插入到表中的顺序如何,此查询的结果都是相同的。您可以尝试将INSERT语句按不同的顺序放在小提琴中。这不会影响结果

此外,当您在OVER子句中刚刚使用ORDER BY时,LAST_值的行为与您在默认窗口中直观地期望的不完全一样。默认窗口是无界前一行和当前行之间的行,而您希望它是无界前一行和无界后一行之间的行。这里有一个答案,答案很简单。此SO答案的链接位于的MSDN页上。因此,一旦在查询中显式指定了行窗口,它将返回所需的内容

如果您想知道将行插入表中的顺序,我认为最简单的方法是使用。因此,表的定义将更改为:

CREATE TABLE Data 
(PK INT IDENTITY(1,1) PRIMARY KEY,
Id1 INT,
Id2 INT)
当您插入到这个表中时,您不需要指定PK的值,服务器将自动生成它。它保证生成的值是唯一的,并且随着正增量参数的增加而增长,即使有许多客户端同时插入到表中。生成的值之间可能存在间隙,但生成值的相对顺序将告诉您在哪一行之后插入了哪一行

SELECT  Id1
        , Id2
        , LAST_VALUE(PK) 
            OVER (PARTITION BY Id1 
            ORDER BY Id2 DESC) AS LastValue
FROM    Data
ORDER BY Id2 ASC
结果


为什么期望这些值?这两个值都是有效的,因为顺序是由Id2完成的,所以它选择其中一个值。如果您是对的,两个解决方案都是有效的。我希望是这样的顺序,因为它是数据插入表中的顺序。我认为我在混合概念,我必须使用MAX而不是LAST_值来得到我想要的。因为结果不是预期的。您可以在此处检查订单返回的结果,因此您是否确实希望根据订单返回最后一个值?或者你想要一个最大值?在这种情况下,我需要最大值,但我有另一种情况,我需要最后插入的值。如果我需要问题适用的最后一个插入值,我不知道如何更改查询来执行该操作。
Id1 Id2 LastValue
2   5   3
2   5   3
2   6   4
2   6   4