4つの乱数(1から4)を取得し、結合して一致するdatabase_id番号を取得する単純なスクリプトがあります。LEFT JOINを使用してスクリプトを実行すると、毎回4行が返されます(予想される結果)。ただし、INNER JOINを使用して実行すると、行の数が変化します(2行、8行の場合もあります)。
論理的には、sys.databasesにdatabase_ids 1〜4の行が存在することがわかっているため、違いはありません。また、(結合するのではなく)4つの行を持つ乱数テーブルから選択しているため、4行以上が返されることはありません。
これはSQL Server 2012と2014の両方で発生します。INNERJOINがさまざまな行数を返す原因は何ですか?
/* 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()) ;
非決定的関数の値に結合がないため、正常に機能すると思います。