Minha consulta de trabalho real era uma junção interna, mas este exemplo simples com junção cruzada parece quase sempre reproduzir o problema.
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT NEWID() TEST_ID
) BB ( B )
Com minha junção interna, eu tinha muitas linhas para as quais adicionei a cada um um GUID usando a função NEWID () e, para cerca de 9 de 10 dessas linhas, a multiplicação com a tabela virtual de 2 linhas produziu os resultados esperados, apenas 2 cópias de o mesmo GUID, enquanto 1 em 10 produziria resultados diferentes. Isso foi inesperado para dizer o mínimo e me deu muita dificuldade tentando encontrar esse bug no meu script de geração de dados de teste.
Se você der uma olhada nas consultas a seguir usando também as funções getdate e sysdatetime não determinísticas, não verá isso, de qualquer maneira - sempre vejo o mesmo valor de data e hora em ambas as linhas do resultado final.
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 )
Atualmente, estou usando o SQL Server 2008 e meu trabalho por enquanto é carregar minhas linhas com GUIDs em uma variável de tabela antes de terminar meu script de geração de dados aleatórios. Depois de tê-los como valores em uma tabela em vez de uma tabela virtual, o problema desaparece.
Eu tenho uma solução alternativa, mas estou procurando maneiras de contornar sem tabelas reais ou variáveis de tabela.
Enquanto escrevia isso, tentei sem sucesso estas possibilidades: 1) colocar o newid () em uma tabela virtual aninhada:
SELECT *
FROM (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
CROSS JOIN (
SELECT TEST_ID
FROM (
SELECT NEWID() TEST_ID
) TT
) BB ( B )
2) envolvendo o newid() dentro de uma expressão de conversão, como:
SELECT CAST(NEWID() AS VARCHAR(100)) TEST_ID
3) invertendo a ordem de aparecimento das tabelas virtuais dentro da expressão join
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS JOIN (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
4) usando aplicação cruzada não correlacionada
SELECT *
FROM (
SELECT NEWID() TEST_ID
) BB ( B )
CROSS APPLY (
SELECT 1 UNION ALL
SELECT 2
) AA ( A )
Pouco antes de finalmente postar esta pergunta, agora tentei com sucesso, ao que parece, uma aplicação cruzada correlacionada:
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 )
Alguém tem alguma outra solução alternativa mais elegante e simples? Eu realmente não quero usar aplicação cruzada ou correlação para uma multiplicação de linha simples, se não for necessário.