Saya menemukan puzzle ini di komentar di sini
CREATE TABLE r (b INT);
SELECT 1 FROM r HAVING 1=1;
SQL Server dan PostgreSQL mengembalikan 1 baris.
MySQL dan Oracle mengembalikan nol baris.
Yang mana yang benar? Atau keduanya sama-sama valid?
aggregate
sql-standard
Martin Smith
sumber
sumber
SELECT COUNT(*) FROM r;
mengembalikan 1 baris (dengan0
), sementaraSELECT COUNT(*) FROM r GROUP BY ();
tidak mengembalikan baris.SELECT 1 WHERE 1=0 HAVING 1=1;
. SQL Server dan PostgreSQL masih mengembalikan satu baris. Oracle menginginkan FROM DUAL dan tidak mengembalikan baris. MySQL tidak mengkompilasi dengan FROM DUAL atau tanpa itu .SELECT 1 AS t FROM (SELECT 1) tmp WHERE 1=0 HAVING 1=1;
1-baris-tidak-ganda dan mengembalikan 0 baris.<group by clause>
, maka“GROUP BY ()”
implisit." Tidakkah seharusnya kedua kueri mengembalikan hasil yang sama?HAVING
berbeda): SQl-biola 2: MEMILIKI hal-hal yang berbedaJawaban:
Sesuai standar:
cara
Kutipan ISO / IEC 9075-2: 2011 7.10 Sintaks Aturan 1 (Bagian dari definisi klausa HAVING):
Ok jadi itu cukup jelas.
Pernyataan:
1=1
adalah kondisi pencarian yang sebenarnya. Saya tidak akan memberikan kutipan untuk ini.Sekarang
setara dengan
Kutipan ISO / IEC 9075-2: 2011 7.10 Aturan Umum 1:
Logika: Karena kondisi pencarian selalu benar, hasilnya adalah
R
, yang merupakan hasil grup dengan ekspresi.Berikut ini adalah kutipan dari Peraturan Umum 7.9 (definisi GROUP BY CLAUSE)
Dengan demikian kita dapat menyimpulkan itu
menghasilkan tabel yang dikelompokkan, terdiri dari satu grup, dengan nol baris (karena R kosong).
Kutipan dari Aturan Umum 7.12, yang mendefinisikan Spesifikasi Kueri (alias pernyataan SELECT):
Oleh karena itu karena tabel memiliki satu grup, itu harus memiliki satu baris hasil.
Jadi
harus mengembalikan set hasil 1 baris.
QED
sumber
Ketika ada
HAVING
klausa, tanpaWHERE
klausa:... maka
GROUP BY ()
tersirat. Jadi, kueri harus sama dengan:... yang seharusnya mengelompokkan semua baris tabel ke dalam satu grup (bahkan jika tabel tidak memiliki baris sama sekali - itu masih satu grup dari 0 baris) dan mengembalikan 1 baris. The
HAVING
denganTrue
kondisi seharusnya tidak berpengaruh sama sekali setelah itu.Dari sudut pandang yang berbeda, berapa banyak baris yang harus kueri seperti ini kembali?
Satu, nol atau "nol atau satu, tergantung pada apakah tabelnya kosong atau tidak"?
Saya pikir satu baris, tidak peduli berapa banyak baris yang
r
dimiliki.sumber
Dari apa yang saya lihat, sepertinya SQLServer dan PostgerSQL tidak repot melihat ke dalam tabel sama sekali:
juga mengembalikan hanya satu baris. Meskipun kata SQLServer docs
itu tidak benar dalam kasus ini -
WHERE 1=1
alih - alihHAVING
mengembalikan jumlah baris yang tepat. Saya akan mengatakan itu bug pengoptimal (atau setidaknya bug dokumentasi) ... Rencana SQLServer menunjukkan 'Pemindaian konstan' dalam kasusHAVING
dan 'pemindaian tabel' untukWHERE
...Perilaku Oracle dan Mysql tampaknya lebih logis dan benar bagi saya ...
sumber
explain
"Hasil (baris = 1) ..." untuk memiliki dan "Pemindaian Seq" untuk "DIMANA" juga tidak melihat ke dalam tabel. .. Saya kira itu entah bagaimana terkait dengan fakta bahwa "FROM" tidak wajib dalam TSQL dan PostgreSQL. Saya tahu Mysql juga tidak memerlukannya, tetapi karena mereka mendukungdual
, mereka mungkin menguraikan kueri yang sedikit berbeda. Saya setuju, ini terdengar seperti spekulasi, tapi saya harap ini masuk akal.