Minha consulta de trabalho real foi uma junção interna, mas este exemplo simples com junção cruzada quase sempre reproduz 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 GUID usando a função NEWID (), e para cerca de 9 em 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 cada 10 produziria resultados diferentes. Isso foi inesperado para dizer o mínimo e me deu muita dificuldade em tentar encontrar esse bug no meu script de geração de dados de teste.
Se você der uma olhada nas consultas a seguir usando as funções getdate e sysdatetime não determinísticas, você não verá isso, de qualquer maneira - sempre vejo o mesmo valor de datetime nas duas linhas de resultados finais.
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 minha solução, 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 oposição à tabela virtual, o problema desaparece.
Eu tenho uma solução alternativa, mas estou procurando maneiras de solucionar essa situação sem tabelas ou variáveis de tabela reais.
Enquanto escrevia isso, tentei sem sucesso as seguintes 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 convertida, como:
SELECT CAST(NEWID() AS VARCHAR(100)) TEST_ID
3) reverter a ordem de aparência das tabelas virtuais na expressão de junção
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 )
Antes de finalmente postar esta pergunta, agora eu tentei isso com sucesso, parece que uma cruz correlacionada se aplica:
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 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.
fonte