harus muncul dalam klausa GROUP BY atau yang akan digunakan dalam fungsi agregat
Saya memiliki sebuah meja yang terlihat seperti ini caller 'makerar'
cname | wmname | avg
--------+-------------+------------------------
canada | zoro | 2.0000000000000000
spain | luffy | 1.00000000000000000000
spain | usopp | 5.0000000000000000
Dan saya ingin memilih maksimum avg untuk setiap cname.
SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname;
tapi aku akan mendapatkan error,
ERROR: column "makerar.wmname" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname;
jadi saya melakukan ini
SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname, wmname;
namun hal ini tidak akan memberikan intented hasil dan keluaran yang salah di bawah ini ditampilkan.
cname | wmname | max
--------+--------+------------------------
canada | zoro | 2.0000000000000000
spain | luffy | 1.00000000000000000000
spain | usopp | 5.0000000000000000
Hasil yang sebenarnya harus
cname | wmname | max
--------+--------+------------------------
canada | zoro | 2.0000000000000000
spain | usopp | 5.0000000000000000
Bagaimana saya bisa pergi tentang memperbaiki masalah ini?
Catatan: tabel Ini adalah PANDANGAN yang dibuat dari operasi sebelumnya.
239
7
Ya, ini adalah umum agregasi masalah. Sebelum SQL3 (1999), bidang yang dipilih harus muncul dalam
GROUP BY
klausul[*].Untuk solusi masalah ini, anda harus menghitung agregat dalam sub-query dan kemudian bergabung dengan dirinya sendiri untuk mendapatkan tambahan kolom anda'd butuhkan untuk menunjukkan:
Tapi anda juga dapat menggunakan fungsi jendela, yang terlihat lebih sederhana:
Satu-satunya hal dengan metode ini adalah bahwa hal itu akan menunjukkan semua catatan (window fungsi tidak kelompok). Tapi itu akan menunjukkan yang benar (yaitu maxed di
cname
level)MAX
untuk negara di setiap baris, sehingga's up untuk anda:Solusinya, bisa dibilang kurang elegan, untuk menunjukkan satu-satunya
(cname, wmname)
tupel pencocokan nilai max, adalah:[*]: Cukup menarik, meskipun spec semacam ini memungkinkan untuk memilih non-dikelompokkan bidang, mesin utama tampaknya tidak benar-benar seperti itu. Oracle dan SQLServer hanya don't membiarkan ini semua. Mysql digunakan untuk memungkinkan secara default, tapi sekarang sejak 5.7 administrator harus mengaktifkan opsi ini (
ONLY_FULL_GROUP_BY
) secara manual pada konfigurasi server untuk fitur ini harus didukung...Di Postgres, anda juga dapat menggunakan khusus
yang BERBEDA PADA (ekspresi)
sintaks:Masalah dengan menentukan non-dikelompokkan dan non-agregat di bidang
group by
memilih adalah bahwa mesin tidak memiliki cara untuk mengetahui yang merekam's bidang itu harus kembali dalam kasus ini. Itu dulu? Itu tadi? Biasanya ada tidak ada catatan yang secara alami sesuai dengan agregat hasil (min
danmax
adalah pengecualian).Namun, ada solusi: membuat bidang yang diperlukan dikumpulkan juga. Di posgres, ini harus bekerja:
Perhatikan bahwa hal ini menciptakan sebuah array dari semua wnames, diperintahkan oleh avg, dan kembali elemen pertama (array dalam postgres adalah 1-based).
Menggunakan
rank()
fungsi jendela:Catatan
Salah satu akan mempertahankan beberapa nilai max per kelompok. Jika anda ingin hanya satu record per kelompok bahkan jika ada lebih dari satu record dengan avg sama dengan max anda harus memeriksa @ypercube's jawaban.
Bagi saya, ini bukan tentang "umum agregasi masalah", tapi hanya mengenai salah query SQL. Satu jawaban yang benar untuk "pilih maksimum avg untuk setiap cname..."
Hasilnya akan menjadi:
Hasil ini secara umum jawaban pertanyaan "Apa hasil yang terbaik bagi masing-masing group?". Kita melihat bahwa hasil yang terbaik untuk spanyol adalah 5 dan kanada yang terbaik hasilnya adalah 2. Itu adalah benar, dan tidak ada kesalahan. Jika kita perlu untuk menampilkan wmname juga, kita harus menjawab pertanyaan: "Apa PERATURAN untuk memilih wmname dihasilkan dari set?" Let's mengubah data masukan sedikit untuk memperjelas kesalahan:
Yang hasil yang anda harapkan pada runnig query ini:
PILIH cname, wmname, MAX(avg) DARI makerar KELOMPOK DENGAN cname;
? Harus ituspanyol+luffy
atauspanyol+usopp
? Mengapa? Hal ini tidak bertekad dalam query bagaimana memilih "baik" wmname jika beberapa yang cocok, sehingga hasilnya juga tidak ditentukan. Yang's mengapa SQL juru kembali kesalahan - query adalah tidak benar.Dalam kata lain, tidak ada jawaban yang benar untuk pertanyaan "siapa Yang terbaik di
spanyol
kelompok?". Luffy tidak lebih baik dari usopp, karena usopp sama "nilai".Baru-baru ini saya mengalami masalah ini, ketika mencoba untuk menghitung menggunakan
kasus
, dan menemukan bahwa mengubah urutanyang
danmenghitung
laporan perbaikan masalah:Alih-alih menggunakan - in yang terakhir, di mana saya mendapat kesalahan apel dan jeruk harus muncul dalam fungsi agregat
Hal ini tampaknya bekerja dengan baik