Berikut ini adalah contoh paling sederhana yang mungkin, meskipun solusi apa pun harus dapat menskalakan namun banyak hasil teratas diperlukan:
Diberikan tabel seperti itu di bawah ini, dengan orang, grup, dan kolom umur, bagaimana Anda mendapatkan 2 orang tertua di setiap grup? (Ikatan dalam kelompok tidak boleh menghasilkan lebih banyak hasil, tetapi berikan 2 pertama dalam urutan abjad)
+ -------- + ------- + ----- + | Orang | Grup | Umur | + -------- + ------- + ----- + | Bob | 1 | 32 | | Jill | 1 | 34 | | Shawn | 1 | 42 | | Jake | 2 | 29 | | Paul | 2 | 36 | | Laura | 2 | 39 | + -------- + ------- + ----- +
Kumpulan hasil yang diinginkan:
+ -------- + ------- + ----- + | Shawn | 1 | 42 | | Jill | 1 | 34 | | Laura | 2 | 39 | | Paul | 2 | 36 | + -------- + ------- + ----- +
CATATAN: Pertanyaan ini dibangun di atas yang sebelumnya - Dapatkan catatan dengan nilai maksimal untuk setiap grup hasil SQL yang dikelompokkan - untuk mendapatkan satu baris teratas dari setiap grup, dan yang menerima jawaban khusus khusus MySQL dari @Bohemian:
select *
from (select * from mytable order by `Group`, Age desc, Person) x
group by `Group`
Senang bisa membangun dari ini, meskipun saya tidak melihat caranya.
Jawaban:
Berikut adalah salah satu cara untuk melakukan ini, menggunakan
UNION ALL
(Lihat SQL Fiddle with Demo ). Ini berfungsi dengan dua grup, jika Anda memiliki lebih dari dua grup, maka Anda perlu menentukangroup
angka dan menambahkan kueri untuk masing-masinggroup
:Ada berbagai cara untuk melakukan ini, lihat artikel ini untuk menentukan rute terbaik untuk situasi Anda:
http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
Edit:
Ini mungkin bekerja untuk Anda juga, itu menghasilkan nomor baris untuk setiap catatan. Menggunakan contoh dari tautan di atas, ini hanya akan mengembalikan catatan-catatan dengan jumlah baris kurang dari atau sama dengan 2:
Lihat Demo
sumber
SELECT
(dan, pada kenyataannya, kadang-kadang mengevaluasi mereka keluar dari urutan). Kunci dari solusi ini adalah untuk menempatkan semua tugas variabel dalam satu ekspresi; berikut adalah contohnya: stackoverflow.com/questions/38535020/… .Di basis data lain Anda bisa melakukan ini menggunakan
ROW_NUMBER
. MySQL tidak mendukungROW_NUMBER
tetapi Anda dapat menggunakan variabel untuk menirunya:Lihat berfungsi online: sqlfiddle
Sunting Saya baru memperhatikan bahwa bluefeet memposting jawaban yang sangat mirip: +1 kepadanya. Namun jawaban ini memiliki dua keunggulan kecil:
Jadi saya akan meninggalkannya di sini kalau-kalau itu bisa membantu seseorang.
sumber
JOIN (SELECT @prev := NULL, @rn := 0) AS vars
. Saya mendapatkan idenya adalah mendeklarasikan variabel kosong, tetapi sepertinya tidak cocok untuk MySql.Coba ini:
DEMO
sumber
a.person
.Bagaimana dengan menggunakan self-join:
memberi saya:
Saya sangat terinspirasi oleh jawaban dari Bill Karwin untuk Memilih 10 catatan teratas untuk setiap kategori
Juga, saya menggunakan SQLite, tetapi ini harus bekerja pada MySQL.
Hal lain: di atas, saya mengganti
group
kolom dengangroupname
kolom untuk kenyamanan.Edit :
Menindaklanjuti komentar OP mengenai hasil dasi yang hilang, saya menambahkan jawaban snuffin untuk menunjukkan semua ikatan. Ini berarti bahwa jika yang terakhir adalah ikatan, lebih dari 2 baris dapat dikembalikan, seperti yang ditunjukkan di bawah ini:
memberi saya:
sumber
ERROR 1242 (21000): Subquery returns more than 1 row
, mungkin karenaGROUP BY
. Ketika saya menjalankanSELECT MIN
subquery sendirian, itu menghasilkan tiga baris:34, 39, 112
dan di sana nampak nilai kedua harus 36, bukan 39.Solusi snuffin tampaknya cukup lambat untuk dieksekusi ketika Anda memiliki banyak baris dan solusi Mark Byers / Rick James dan Bluefeet tidak berfungsi pada lingkungan saya (MySQL 5.6) karena pesanan oleh diterapkan setelah eksekusi pilih, jadi di sini ada varian solusi Marc Byers / Rick James untuk memperbaiki masalah ini (dengan pilihan tambahan yang diisikan):
Saya mencoba permintaan serupa pada tabel yang memiliki 5 juta baris dan hasilnya kembali dalam waktu kurang dari 3 detik
sumber
LIMIT 9999999
ke tabel turunan mana pun denganORDER BY
. Ini dapat mencegahORDER BY
dari diabaikan.Lihat ini:
SQL Fiddle: http://sqlfiddle.com/#!2/cdbb6/15
sumber
max(internal_version - 1)
- jadi lebih sedikit stres :)Jika jawaban lain tidak cukup cepat. Cobalah kode ini :
Keluaran:
sumber
Saya ingin membagikan ini karena saya menghabiskan waktu yang lama mencari cara mudah untuk mengimplementasikan ini dalam program java yang sedang saya kerjakan. Ini tidak cukup memberikan output yang Anda cari tetapi lebih dekat. Fungsi di mysql disebut
GROUP_CONCAT()
berfungsi dengan sangat baik untuk menentukan berapa banyak hasil yang dikembalikan di masing-masing kelompok. MenggunakanLIMIT
atau cara-cara mewah lainnya untuk mencoba melakukan ini denganCOUNT
tidak berhasil untuk saya. Jadi, jika Anda mau menerima hasil modifikasi, itu solusi yang bagus. Katakanlah saya memiliki meja yang disebut 'siswa' dengan id siswa, jenis kelamin mereka, dan gpa. Katakanlah saya ingin top 5 gpa untuk setiap jenis kelamin. Maka saya bisa menulis kueri seperti iniPerhatikan bahwa parameter '5' menunjukkan berapa banyak entri untuk digabungkan ke dalam setiap baris
Dan hasilnya akan terlihat seperti
Anda juga dapat mengubah
ORDER BY
variabel dan memesannya dengan cara yang berbeda. Jadi jika saya memiliki usia siswa saya dapat mengganti 'gpa desc' dengan 'age desc' dan itu akan berhasil! Anda juga dapat menambahkan variabel ke grup dengan pernyataan untuk mendapatkan lebih banyak kolom di output. Jadi ini hanya cara yang saya temukan yang cukup fleksibel dan berfungsi baik jika Anda ok dengan hanya daftar hasil.sumber
Dalam SQL Server
row_numer()
adalah fungsi yang kuat yang bisa mendapatkan hasil dengan mudah seperti di bawah inisumber
Ada jawaban yang sangat bagus untuk masalah ini di MySQL - Cara Mendapatkan Baris N Top per Setiap Grup
Berdasarkan solusi dalam tautan yang dirujuk, kueri Anda akan seperti:
di mana
n
adalahtop n
danyour_table
adalah nama meja Anda.Saya pikir penjelasan dalam referensi sangat jelas. Untuk referensi cepat saya akan menyalin dan menempelkannya di sini:
sumber