Saya memiliki skrip sederhana yang mendapat empat angka acak (1 hingga 4) dan kemudian bergabung kembali untuk mendapatkan nomor database_id yang cocok. Ketika saya menjalankan skrip dengan BERGABUNG KIRI, saya mendapatkan empat baris kembali setiap kali (hasil yang diharapkan). Namun, ketika saya menjalankannya dengan INNER JOIN, saya mendapatkan jumlah baris yang bervariasi - terkadang dua, kadang delapan.
Secara logis, seharusnya tidak ada perbedaan karena saya tahu baris dengan database_ids 1-4 ada di sys.databases. Dan karena kita memilih dari tabel angka acak dengan empat baris (sebagai lawan bergabung dengannya), seharusnya tidak pernah ada lebih dari empat baris yang dikembalikan.
Ini terjadi di SQL Server 2012 dan 2014. Apa yang menyebabkan INNER JOIN untuk mengembalikan jumlah baris yang berbeda?
/* 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;
sumber
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()) ;
Saya kira itu berfungsi dengan baik karena tidak ada gabungan pada nilai fungsi non-deterministik.Jawaban:
Dengan menambahkan SELECT tambahan itu mendorong evaluasi skalar komputasi lebih dalam ke dalam rencana dan memberikan predikat gabungan, skalar komputasi di atas kemudian referensi yang sebelumnya.
Masih menggali mengapa terlambat menunggu untuk melakukannya, tetapi saat ini membaca posting ini oleh Paul White ( https://sql.kiwi/2012/09/compute-scalars-expressions-and-execution-plan-performance.html ) . Mungkin itu ada hubungannya dengan fakta bahwa NEWID tidak deterministik?
sumber
Ini mungkin memberikan beberapa wawasan sampai salah satu dari orang-orang yang lebih pintar di situs tersebut berdebat.
Saya menempatkan hasil acak ke dalam tabel sementara dan saya secara konsisten mendapatkan 4 hasil terlepas dari tipe gabungan.
Jika saya membandingkan paket kueri antara kueri kedua dan variasinya dengan variabel tabel, saya bisa melihat ada perbedaan yang pasti antara keduanya. X merah
No Join Predicate
begitu sepertinya aneh bagi otak pengembang gua sayaJika saya menghilangkan bit acak dari kueri ke konstanta
1 % (4)
, rencana saya terlihat lebih baik tetapi Compute Scalar dihilangkan sehingga membuat saya melihat lebih dekatIni menghitung ekspresi untuk angka acak setelah bergabung. Apakah itu yang diharapkan, saya masih tetap pergi ke penyihir internal di situs tetapi setidaknya itu sebabnya Anda mendapatkan hasil yang bervariasi dalam bergabung Anda.
2014
Bagi mereka yang bermain bersama di rumah, rencana kueri di atas dihasilkan dari instance 2008 R2. Paket 2014 terlihat berbeda tetapi operasi Hitung Skalar tetap setelah bergabung.
Ini adalah paket kueri untuk 2014 menggunakan ekspresi konstan
Ini adalah paket kueri untuk instance 2014 yang menggunakan ekspresi newid.
Ini tampaknya adalah dengan desain, masalah Connect di sini. Terima kasih kepada @paulWhite karena mengetahui hal itu ada.
sumber