ฉันมีสคริปต์ง่าย ๆ ที่ได้รับตัวเลขสุ่มสี่ตัว (1 ถึง 4) จากนั้นก็กลับมารวมกันเพื่อรับหมายเลข database_id ที่ตรงกัน เมื่อฉันรันสคริปต์ด้วย LEFT JOIN ฉันจะได้สี่แถวกลับมาทุกครั้ง (ผลลัพธ์ที่คาดหวัง) อย่างไรก็ตามเมื่อฉันเรียกใช้ด้วยการเข้าร่วมภายในฉันได้รับจำนวนแถวที่แตกต่างกัน - บางครั้งสองครั้งบางครั้งแปด
เหตุผลไม่ควรมีความแตกต่างเพราะฉันรู้ว่าแถวที่มี database_ids 1-4 อยู่ในฐานข้อมูล และเนื่องจากเราเลือกจากตารางตัวเลขสุ่มที่มีสี่แถว (ซึ่งต่างจากการเข้าร่วมกับตาราง) จึงไม่ควรมีการส่งคืนเกินสี่แถว
สิ่งนี้เกิดขึ้นทั้งใน 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()) ;
ฉันเดาว่ามันทำงานได้ดีเพราะไม่มีการเข้าร่วมกับค่าของฟังก์ชันที่ไม่ได้กำหนดค่าไว้