У меня есть простой скрипт, который получает четыре случайных числа (от 1 до 4), а затем присоединяется обратно, чтобы получить соответствующий номер database_id. Когда я запускаю скрипт с LEFT JOIN, я каждый раз получаю четыре строки назад (ожидаемый результат). Однако, когда я запускаю его с INNER JOIN, я получаю различное количество строк - иногда две, иногда восемь.
Логически, не должно быть никакой разницы, потому что я знаю, что строки с database_ids 1-4 существуют в sys.databases. И поскольку мы выбираем из таблицы случайных чисел с четырьмя строками (в отличие от присоединения к ней), никогда не должно быть больше четырех строк.
Это происходит как в SQL Server 2012, так и в 2014 году. Что заставляет INNER JOIN возвращать различное количество строк?
/* 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()) ;
я думаю, что это работает нормально, потому что нет соединения со значением недетерминированной функции.