Mam prosty skrypt, który pobiera cztery liczby losowe (od 1 do 4), a następnie dołącza z powrotem, aby uzyskać pasujący numer id_bazy_danych. Kiedy uruchamiam skrypt z LEFT JOIN, za każdym razem otrzymuję cztery wiersze (oczekiwany wynik). Kiedy jednak uruchamiam go z WEJŚCIEM WEWNĘTRZNYM, otrzymuję różną liczbę wierszy - czasem dwa, a czasem osiem.
Logicznie rzecz biorąc, nie powinno być żadnej różnicy, ponieważ wiem, że wiersze z id_bazy_danych 1-4 istnieją w sys.databases. A ponieważ wybieramy z tabeli liczb losowych z czterema wierszami (w przeciwieństwie do łączenia się z nią), nigdy nie powinno być zwracanych więcej niż cztery wiersze.
Dzieje się tak zarówno w SQL Server 2012, jak i 2014. Co powoduje, że INNER JOIN zwraca różną liczbę wierszy?
/* 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()) ;
Myślę, że działa dobrze, ponieważ nie ma sprzężenia wartości funkcji niedeterministycznej.