尝试generate a seeded random ordering时我注意到了这个问题,现在在SQL Server 2008 R2(RTM)和SEDE上都进行了复制,即SQL Server 2012(SP1):
当您ORDER BY
VarBinary
子 - SELECT
字段时,订单不会发生。
在查询计划(上面的SEDE)中,您可以看到没有SORT:
SELECT [id]
,y.x As ryx
,RAND(y.x) As yx
FROM #Test, (SELECT CONVERT(varbinary, NEWID()) As x) y
ORDER BY ryx
我尝试过的所有其他变体(你可以在SEDE查询中看到它们,以及如果你将它们编辑为ORDER BY yx
)。
我查看了MSDN,并且仅在确定索引后确认VarBinary
使用MACHINE collation。
这只是一个错误或记录不完整的功能吗? : - )
答案 0 :(得分:1)
这是一个错误。
Create Table #Test(Id Int NOT NULL)
INSERT Into #Test VALUES(1)
INSERT Into #Test VALUES(2)
SELECT @@VERSION
SELECT *
FROM (
SELECT [id]
,y.x As ryx
,RAND(y.x) As yx
FROM #Test, (SELECT CONVERT(varbinary,NEWID()) As x) y
) x
ORDER BY ryx --order by outside!
示例结果:
id ryx
----------- -----------------------------------
1 0xC15FAED68C9A134882A2C977C46F1B8D --wrong order
2 0x532169D935535543BE0E0B24CA5D04FB --wrong order
在此查询中,order by
显然位于外部。生成派生表x
的方式无关紧要。 order by
必须适用。行以未按顺序返回。
将其报告给Microsoft Connect。这是一个优化错误。
答案 1 :(得分:0)
在将此添加到Connect的方式上,我note NEWID()
在表达式中很危险,因为 “按设计”表达式每次都会重新评估它们被访问,而不是每个“本地”行一次。
这进一步讨论here,其中解释了SQL Server的设计者决定优化精度(与大多数编程语言编译器相反)。
所以,在我看到Connect submission的实际结果之前,我猜这是在转换为VarBinary时处于“错误”位置时略微过度优化的结果。
具体来说,这是works:
SELECT *
FROM (
SELECT [id]
,CONVERT(varbinary,y.x) As ryx
,RAND(CONVERT(varbinary,y.x)) As yx
FROM #Test, (SELECT NEWID() As x) y
)x
ORDER BY ryx
其答案中的usr's query没有。