我一直在调试以下声明几个小时:
SELECT
(
SELECT t1.anotherColumn
FROM table1 t1
WHERE t1.aColumn=(1+ABS(Checksum(NewId()))%54)
) res, *
FROM
(
SELECT TOP 200 * --PLEASE NOTICE HERE
FROM table2
)RESULT
问题是始终res
每行包含相同的值。现在,如果我将查询语句中突出显示的200
更改为176
以下的任何数字,则会显示table1
的随机行,这是所需的结果!
请注意54
对结果没有影响,只是因为我的表有{54}个不同的值,从1到54 aColumn
。
我在不同的表上尝试过这个查询,这种奇怪的行为会重复出现!
答案 0 :(得分:4)
结果的差异可以通过查询计划的差异来解释。
SQL优化器可以选择使用Table Spool / Lazy Spool运算符。在这种情况下,NEWID()被调用一次,GUID存储在临时表中并用于所有其他行。
https://technet.microsoft.com/en-us/library/ms191221(v=sql.105).aspx
... 更新: 可以通过在底部添加以下行来修复查询计划:
option(use plan
N'
<your XML plan>
')
要捕获“好”的XML计划,请运行
SET SHOWPLAN_XML ON
并执行显示预期结果的查询。将其复制粘贴到OPTION(使用计划......)
此解决方案适用于大量行(数百万)
答案 1 :(得分:2)
这将强制子查询在每一行上重新获得,并避免复杂的随机逻辑。
SELECT top 200
(SELECT top 1 t1.anotherColumn from table1 t1 with( nolock ) where t2.t2Id is not null order by newid() ) res,
*
FROM table2 t2
它的工作原理是因为newid()已经是一个随机唯一标识符,而table2上的比较强制对table1中的每一行检查table1的每一行。