我的实际工作查询是一个内部联接,但是这个带有交叉联接的简单示例似乎几乎总是重现了该问题。
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT NEWID() TEST_ID
) BB ( B )
对于我的内部联接,我有很多行,我使用NEWID()函数向每个行添加了一个GUID,对于10行中的大约9行,与2行虚拟表的乘法产生了预期的结果,只有2个副本相同的GUID,而十分之1会产生不同的结果。至少可以说这是出乎意料的,这让我很难在测试数据生成脚本中找到此错误。
如果使用非确定性getdate和sysdatetime函数查看以下查询,您将不会看到此信息,无论如何我都不会看到-我总是在两个最终结果行中看到相同的datetime值。
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT GETDATE() TEST_ID
) BB ( B )
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT SYSDATETIME() TEST_ID
) BB ( B )
我当前正在使用SQL Server 2008,目前的解决方法是在完成随机数据生成脚本之前,将具有GUID的行加载到表变量中。一旦将它们作为表中的值而不是虚拟表中的值,问题就消失了。
我有一个解决方法,但是我正在寻找没有实际表或表变量的解决方法。
在编写此代码时,我尝试了以下几种尝试,但均未成功:1)将newid()放入嵌套的虚拟表中:
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT TEST_ID
FROM (
SELECT NEWID() TEST_ID
) TT
) BB ( B )
2)将newid()包装在强制转换表达式中,例如:
SELECT CAST(NEWID() AS VARCHAR(100)) TEST_ID
3)反转连接表达式中虚拟表的出现顺序
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS JOIN (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
4)使用不相关的交叉应用
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS APPLY (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
在最终发布这个问题之前,现在我似乎成功地尝试了这个,相关的交叉适用:
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS APPLY (
SELECT A
FROM (
SELECT 1 UNION ALL
SELECT 2
) TT ( A )
WHERE BB.B IS NOT NULL
) AA ( A )
有人还有其他更优雅,更简单的解决方法吗?如果不需要,我真的不想使用交叉应用或相关性来进行简单的行乘法。