Eu tenho um script simples que obtém quatro números aleatórios (1 a 4) e depois se junta novamente para obter o número database_id correspondente. Quando executo o script com LEFT JOIN, recebo quatro linhas sempre (o resultado esperado). No entanto, quando o executo com um INNER JOIN, recebo um número variável de linhas - às vezes duas, às vezes oito.
Logicamente, não deve haver nenhuma diferença, porque eu sei que existem linhas com database_ids 1-4 no sys.databases. E como estamos selecionando da tabela de números aleatórios com quatro linhas (em vez de ingressar nela), nunca deve haver mais do que quatro linhas retornadas.
Isso acontece no SQL Server 2012 e 2014. O que está fazendo com que o INNER JOIN retorne vários números de linhas?
/* Works as expected -- always four rows */
SELECT rando.RandomNumber, d.database_id
FROM
(SELECT 1 + ABS(CHECKSUM(NEWID())) % (4) AS RandomNumber
FROM sys.databases WHERE database_id <= 4) AS rando
LEFT JOIN sys.databases d ON rando.RandomNumber = d.database_id;
/* Returns a varying number of rows */
SELECT rando.RandomNumber, d.database_id
FROM
(SELECT 1 + ABS(CHECKSUM(NEWID())) % (4) AS RandomNumber
FROM sys.databases WHERE database_id <= 4) AS rando
INNER JOIN sys.databases d ON rando.RandomNumber = d.database_id;
/* Also returns a varying number of rows */
WITH rando AS (
SELECT 1 + ABS(CHECKSUM(NEWID())) % (4) AS RandomNumber
FROM sys.databases WHERE database_id <= 4
)
SELECT r.RandomNumber, d.database_id
FROM rando AS r
INNER JOIN sys.databases d ON r.RandomNumber = d.database_id;
SELECT TOP (4) d.database_id FROM sys.databases AS d CROSS JOIN (VALUES (1),(2),(3),(4)) AS multi (i) WHERE d.database_id <= 4 ORDER BY CHECKSUM(NEWID()) ;
acho que funciona bem porque não há junção no valor da função não determinística.