J'ai un script simple qui obtient quatre nombres aléatoires (1 à 4), puis se joint à nouveau pour obtenir le numéro de database_id correspondant. Lorsque j'exécute le script avec un LEFT JOIN, j'obtiens à chaque fois quatre lignes (le résultat attendu). Cependant, lorsque je l'exécute avec une INNER JOIN, j'obtiens un nombre variable de lignes - parfois deux, parfois huit.
Logiquement, il ne devrait pas y avoir de différence car je sais que des lignes avec database_ids 1-4 existent dans sys.databases. Et parce que nous sélectionnons dans la table des nombres aléatoires avec quatre lignes (par opposition à la joindre à elle), il ne devrait jamais y avoir plus de quatre lignes retournées.
Cela se produit à la fois dans SQL Server 2012 et 2014. Qu'est-ce qui pousse INNER JOIN à retourner un nombre variable de lignes?
/* 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()) ;
je suppose que cela fonctionne bien car il n'y a pas de jointure sur la valeur de la fonction non déterministe.