我的实际工作查询是内部联接,但这个带有交叉联接的简单示例似乎几乎总是重现问题。
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,而十分之一会产生不同的结果。这至少可以说是出乎意料的,让我很难在我的测试数据生成脚本中找到这个错误。
如果您使用非确定性 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 )
有人有其他更优雅、更简单的解决方法吗?如果我不需要的话,我真的不想使用交叉应用或相关来进行简单的行乘法。