Standar ANSI SQL mendefinisikan (bab 6.5, mengatur spesifikasi fungsi) perilaku berikut untuk fungsi agregat pada set hasil kosong:
COUNT(...) = 0
AVG(...) = NULL
MIN(...) = NULL
MAX(...) = NULL
SUM(...) = NULL
Mengembalikan NULL untuk AVG, MIN, dan MAX sangat masuk akal, karena rata-rata, minimum, dan maksimum dari set kosong tidak ditentukan.
Yang terakhir, bagaimanapun, mengganggu saya: Secara matematis, SUM dari himpunan kosong adalah didefinisikan dengan baik: 0
. Menggunakan 0, elemen netral penambahan, karena casing dasar membuat semuanya konsisten:
SUM({}) = 0 = 0
SUM({5}) = 5 = 0 + 5
SUM({5, 3}) = 8 = 0 + 5 + 3
SUM({5, NULL}) = NULL = 0 + 5 + NULL
Mendefinisikan SUM({})
sebagai null
dasarnya membuat "tidak ada baris" kasus khusus yang tidak cocok dengan orang lain:
SUM({}) = NULL = NULL
SUM({5}) = 5 != NULL + 5 (= NULL)
SUM({5, 3}) = 8 != NULL + 5 + 3 (= NULL)
Apakah ada beberapa keuntungan nyata dari pilihan yang dibuat (SUM sedang NULL) yang saya lewatkan?
Jawaban:
Saya takut bahwa alasannya adalah hanya karena aturan ditetapkan secara adhoc (seperti "fitur" standar ISO SQL lainnya) pada saat agregasi SQL dan hubungannya dengan matematika kurang dipahami daripada sekarang. (*).
Itu hanya salah satu dari banyak inkonsistensi dalam bahasa SQL. Mereka membuat bahasa lebih sulit untuk diajarkan, lebih sulit untuk dipelajari, lebih sulit untuk dipahami, lebih sulit untuk digunakan, lebih sulit untuk apa pun yang Anda inginkan, tetapi hanya seperti itu keadaannya. Aturan tidak dapat diubah "dingin" dan "begitu saja", untuk alasan yang jelas dari kompatibilitas ke belakang (Jika komite ISO menerbitkan versi final dari standar, dan vendor kemudian mulai menerapkan standar itu, maka vendor tersebut tidak akan menghargai itu sangat banyak jika dalam versi berikutnya, aturan diubah sedemikian rupa sehingga implementasi (compliant) versi lama dari standar "secara otomatis gagal memenuhi" versi baru ...)
(*) Sekarang lebih baik dipahami bahwa agregasi atas set kosong berperilaku lebih konsisten jika mereka secara sistematis mengembalikan nilai identitas (= apa yang Anda sebut 'elemen netral') dari operator biner yang mendasarinya. Operator biner yang mendasari untuk COUNT dan SUM adalah tambahan, dan nilai identitasnya adalah nol. Untuk MIN dan MAX, nilai identitas itu adalah nilai tertinggi dan terendah dari jenis yang ada, masing-masing, jika jenis yang bersangkutan terbatas. Kasus-kasus seperti rata-rata, cara harmonis, median, dll sangat rumit dan eksotis dalam hal ini.
sumber
HIGHEST()
banyak tidak menjadi elemen dari tipe data, seperti untuk Reals di mana identitas akan menjadi-Infinity
(dan+Infinity
untukLOWEST()
)Dalam arti pragmatis, hasil yang ada
NULL
berguna. Pertimbangkan tabel dan pernyataan berikut:Pernyataan pertama mengembalikan NULL dan yang kedua mengembalikan nol. Jika set kosong mengembalikan nol untuk
SUM
kita akan membutuhkan cara lain untuk membedakan jumlah sebenarnya dari nol dari set kosong, mungkin menggunakan hitungan. Jika kita memang menginginkan nol untuk set kosong maka sederhanaCOALESCE
akan melengkapi persyaratan itu.sumber
COALESCE()
seperti ini tidak akan membedakan (0
) jumlah set kosong dari (NULL
) jumlah (katakanlah tabel memiliki(10, NULL)
baris.SUM
kolom dan kembali nol saya tahu tanpa harus memeriksa bahwa setidaknya ada satu baris NULL yang digunakan untuk menunjukkan kepada saya hasilnya.DECODE(count(c2),0,NULL,sum(c2))
ketika itu.Perbedaan utama yang bisa saya lihat adalah terkait dengan tipe data. COUNT memiliki jenis pengembalian yang didefinisikan dengan baik: Seluruh nomor. Yang lainnya tergantung pada jenis kolom / ekspresi yang mereka lihat. Jenis pengembalian mereka harus kompatibel dengan semua anggota set (bayangkan float, mata uang, desimal, bcd, rentang waktu, ...). Karena tidak ada set Anda tidak dapat menyiratkan tipe kembali, sehingga NULL adalah pilihan terbaik Anda.
Catatan: Dalam kebanyakan kasus, Anda dapat menyiratkan tipe kembali dari jenis kolom yang Anda lihat, tetapi Anda dapat melakukan SUM tidak hanya pada kolom tetapi pada semua jenis hal. Mengimplikasikan tipe pengembalian mungkin menjadi sangat sulit jika bukan tidak mungkin dalam keadaan tertentu, terutama ketika Anda memikirkan kemungkinan perluasan standar (tipe dinamis muncul di pikiran).
sumber
SUM(column)
ekspresi? Bukankah kita memiliki tabel kosong - dan di sana semua kolom memiliki tipe yang didefinisikan? Mengapa harus berbeda untuk set hasil kosong?24 + 56.07 + '2012-10-05' + 'Red'
? Maksud saya tidak ada masalah dalam mengkhawatirkan bagaimanaSUM()
akan berperilaku ketika kita memiliki masalah mendefinisikan penambahan.