Perilaku Agregat Aliran Ganjil

11

Pertanyaan:

declare @X xml = '
<item ID = "0"/>
<item ID = "1"/>
<item/>
<item/>';

select I.X.value('@ID', 'int')
from @X.nodes('/item') as I(X);

Hasil:

-----------
0
1
NULL
NULL

Rencana eksekusi:

masukkan deskripsi gambar di sini

Cabang atas merobek XML menjadi empat baris dan cabang bawah mengambil nilai untuk atribut ID.

Apa yang menurut saya ganjil adalah jumlah baris yang dikembalikan dari operator Agregat Stream. 2 baris yang berasal dari Filter adalah IDatribut dari itemnode pertama dan kedua dalam XML. Agregat Stream mengembalikan empat baris, satu untuk setiap baris input, secara efektif mengubah Inner Join menjadi Outer Join.

Apakah ini sesuatu yang Stream Aggregate lakukan dalam keadaan lain juga atau hanya sesuatu yang aneh terjadi ketika melakukan permintaan XML?

Saya tidak dapat melihat petunjuk apa pun dalam versi XML dari rencana kueri bahwa Agregat Stream ini harus berperilaku berbeda dari Agregat Stream lain yang saya perhatikan sebelumnya.

Mikael Eriksson
sumber

Jawaban:

13

Agregat adalah agregat skalar (tidak ada grup berdasarkan klausa). Ini didefinisikan dalam SQL Server untuk selalu menghasilkan baris, bahkan jika inputnya kosong.

Untuk agregat skalar , misalnya MAXtanpa baris NULL, COUNTtanpa baris adalah nol, misalnya. Pengoptimal tahu semua tentang ini, dan dapat mengubah sambungan luar menjadi sambungan dalam dalam situasi yang sesuai.

-- NULL for a scalar aggregate
SELECT MAX(V.v) FROM (VALUES(1)) AS V (v) WHERE V.v = 2;

-- No row for a vector aggregate
SELECT MAX(V.v) FROM (VALUES(1)) AS V (v) WHERE V.v = 2 GROUP BY ();

Untuk informasi lebih lanjut tentang agregat, lihat artikel saya Bersenang-senang dengan Agregat Skal dan Vektor .

Paul White 9
sumber
10

Yang perlu diingat di sini adalah rencana eksekusi menyedot data melalui.

Jadi operator Nested Loop memanggil Stream Aggregate 4 kali. Agregat Stream memanggil Filter 4 kali juga, tetapi hanya mendapat nilai dua kali.

Jadi Stream Aggregate memberikan empat nilai. Dua kali memberi nilai, dan dua kali memberi Null.

Rob Farley
sumber