这是我可以重现问题的最简单的例子。因此它看起来有点做作,但请耐心等待。
declare @t table(number int)
insert into @t values (1), (2)
declare @sum bigint = 0
select @sum = @sum + number
from (select top 2 number from @t order by number) subquery
order by number desc
select @sum
Here's the query on the data explorer
我希望这会返回3,即表@t
中值的总和。相反,它会返回1.
执行以下任何操作都会导致查询正确返回3:
@t.number
和@sum
具有相同的类型(将@sum
设为int
或@t.number
设bigint
)。order by
order by
order by
添加到内部版本或从外部版本中删除desc
来使from @t
排序方向相同int
)这些事情都不会让我觉得应该改变这个查询的行为。
交换排序顺序(在子查询中降序,在外部升序)将使查询返回2而不是1.
类似的事情发生在字符串而不是数字上,因此不限于bigint
和Microsoft SQL Server 2014 - 12.0.2000.8 (X64)
Feb 20 2014 20:04:26
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 10586: )
。
SQL Server 2014和2016都会发生这种情况,或者确切地说
Microsoft SQL Server 2016 (RTM-CU1) (KB3164674) - 13.0.2149.0 (X64)
Jul 11 2016 22:05:22
Copyright (c) Microsoft Corporation
Enterprise Edition: Core-based Licensing (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: )
和
a.png
(后者是数据浏览器)。
发生了什么事?
答案 0 :(得分:1)
答案似乎是您依赖于在Sql Server 2012中发生更改的未记录的行为。
根据文件:
SELECT @local_variable通常用于将单个值返回到变量中。但是,当expression是列的名称时,它可以返回多个值。如果SELECT语句返回多个值,则为变量分配最后返回的值。
没有记录如果目标变量(要分配给)是源表达式的一部分会发生什么。看来这种行为已经改变了。在早期版本中,变量将为每一行分配一次,但这似乎不再发生。
这对于&#34; group concat&#34;的许多功能最为明显。诀窍停止工作:
SELECT @sentence = @sentence + ' ' + word from SENTENCE_WORDS order by position
这些通常被xml concat技巧取代。
set @sentence = (
select word as "text()", ' ' as "text()"
from SENTENCE_WORDS
order by position
for xml path(''), root('root'), type
).value('(/root)[1]', 'nvarchar(max)')
答案 1 :(得分:0)
删除第二个ORDER BY(即#34;按编号desc&#34排序)。
您正在使用T-SQL的未记录功能(我相信它被称为ROW连接?),但不保证在未来的SQL版本中可以使用。它有点hacky,但非常有用!正如您所发现的,当您使用ORDER BY子句时它会中断。这是使用行连接的已知问题。