Meja saya adalah:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
3 | 10 | 03/03/2009 | john | 300
4 | 11 | 03/03/2009 | juliet | 200
6 | 12 | 03/03/2009 | borat | 500
7 | 13 | 24/12/2008 | borat | 600
8 | 13 | 01/01/2009 | borat | 700
Saya perlu memilih masing-masing yang berbeda home
memegang nilai maksimum datetime
.
Hasilnya adalah:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
8 | 13 | 01/01/2009 | borat | 700
Saya telah mencoba:
-- 1 ..by the MySQL manual:
SELECT DISTINCT
home,
id,
datetime AS dt,
player,
resource
FROM topten t1
WHERE datetime = (SELECT
MAX(t2.datetime)
FROM topten t2
GROUP BY home)
GROUP BY datetime
ORDER BY datetime DESC
Tidak bekerja Hasil-set memiliki 130 baris meskipun database menampung 187. Hasil mencakup beberapa duplikat home
.
-- 2 ..join
SELECT
s1.id,
s1.home,
s1.datetime,
s1.player,
s1.resource
FROM topten s1
JOIN (SELECT
id,
MAX(datetime) AS dt
FROM topten
GROUP BY id) AS s2
ON s1.id = s2.id
ORDER BY datetime
Nggak. Memberikan semua catatan.
-- 3 ..something exotic:
Dengan berbagai hasil.
id
,player
danresource
baris non-max untuk rumah yang diberikan yaitu untuk rumah = 10 Anda bisa mendapatkan:3 | 10 | 04/03/2009 | john | 300
Dengan kata lain itu tidak menjamin bahwa semua kolom dari baris dalam resultset akan menjadi milik ke max (datetime) untuk rumah yang diberikan.MySQL
Solusi tercepat , tanpa pertanyaan dalam dan tanpaGROUP BY
:Penjelasan :
Gabung tabel dengan dirinya sendiri menggunakan
home
kolom. PenggunaanLEFT JOIN
memastikan semua baris dari tabelm
muncul di set hasil. Mereka yang tidak memiliki kecocokan dalam tabelb
akan memilikiNULL
s untuk kolomb
.Kondisi lain pada permintaan
JOIN
untuk mencocokkan hanya baris darib
yang memiliki nilai lebih besar padadatetime
kolom daripada baris darim
.Menggunakan data yang diposting dalam pertanyaan,
LEFT JOIN
akan menghasilkan pasangan ini:Akhirnya,
WHERE
klausa menjaga hanya pasangan yang memilikiNULL
s di kolomb
(mereka ditandai dengan*
dalam tabel di atas); ini berarti, karena kondisi kedua dariJOIN
klausa, baris yang dipilih darim
memiliki nilai terbesar dalam kolomdatetime
.Baca SQL Antipatterns: Menghindari Jebakan buku Pemrograman Database untuk tips SQL lainnya.
sumber
SQLite
, yang pertama jauh lebih lambat dari versi La Voie ketika tidak ada indeks pada kolom yang cocok (yaitu "rumah"). (Diuji dengan baris 24k menghasilkan barishome
dandatetime
dandatetime
adalah maksimum untuk yang khusus ituhome
?ON
klausa. Fe... ON ... AND m.id < b.id
untuk menjaga entri terbaru (yang memiliki terbesarid
) ketika dua baris memiliki nilaihome
dandatetime
kolom yang sama dan itu adalah maksimumdatetime
.Ini dia versi T-SQL :
EDIT
Sayangnya, tidak ada fungsi RANK () OVER di MySQL.
Tapi itu bisa ditiru, lihat Fungsi Emulasi Analytic (Peringkat AKA) dengan MySQL .
Jadi ini adalah versi MySQL :
sumber
Ini akan berfungsi bahkan jika Anda memiliki dua atau lebih baris untuk masing-masing
home
dengan yang samaDATETIME
:sumber
WHERE ti.home = t1.home
- bisakah Anda menjelaskan sintaksnya?select
Permintaan yang memiliki garisWHERE ti.home = t1.home
tidak perluFROM
klausa yang mendefinisikant1
. Jadi bagaimana ini digunakan?Saya pikir ini akan memberi Anda hasil yang diinginkan:
TETAPI jika Anda membutuhkan kolom lain juga, cukup gabung dengan tabel asli (periksa
Michael La Voie
jawaban)Salam Hormat.
sumber
Karena orang-orang tampaknya terus mengikuti utas ini (tanggal komentar berkisar 1,5 tahun) tidak semudah ini:
SELECT * FROM (SELECT * FROM topten ORDER BY datetime DESC) tmp GROUP BY home
Tidak diperlukan fungsi agregasi ...
Bersulang.
sumber
Anda juga dapat mencoba yang satu ini dan untuk tabel besar kinerja query akan lebih baik. Ini berfungsi ketika tidak ada lebih dari dua catatan untuk setiap rumah dan tanggalnya berbeda. Permintaan MySQL umum yang lebih baik adalah satu dari Michael La Voie di atas.
Atau dalam kasus Postgres atau db yang menyediakan fungsi analitik coba
sumber
SQLite
, yang pertama jauh lebih lambat dari versi La Voie ketika tidak ada indeks pada kolom yang cocok (yaitu "rumah").Ini berfungsi pada Oracle:
sumber
sumber
Coba ini untuk SQL Server:
sumber
sumber
Berikut adalah versi MySQL yang mencetak hanya satu entri di mana ada duplikat MAX (datetime) dalam sebuah grup.
Anda bisa menguji di sini http://www.sqlfiddle.com/#!2/0a4ae/1
Contoh data
Versi MySQL dengan variabel Pengguna
Outout Jawaban yang Diterima
sumber
Cara lain untuk mendapatkan baris terbaru per grup menggunakan sub kueri yang pada dasarnya menghitung peringkat untuk setiap baris per grup dan kemudian menyaring baris terbaru Anda dengan peringkat = 1
DEMO
Berikut ini adalah demo visual untuk peringkat no untuk setiap baris untuk pemahaman yang lebih baik
Kueri di atas akan gagal dan akan mengembalikan lebih dari 1 baris untuk situasi di atas. Untuk menutupi situasi ini akan diperlukan kriteria / parameter / kolom lain untuk memutuskan baris mana yang harus diambil yang berada dalam situasi di atas. Dengan melihat kumpulan data sampel, saya berasumsi ada kolom kunci utama
id
yang harus disetel ke kenaikan otomatis. Jadi kita bisa menggunakan kolom ini untuk memilih baris terbaru dengan mengubah kueri yang sama dengan bantuanCASE
pernyataan sepertiDEMO
Kueri di atas akan memilih baris dengan id tertinggi di antara yang sama
datetime
nilai-nilaidemo visual untuk peringkat no untuk setiap baris
sumber
Mengapa tidak menggunakan: SELECT home, MAX (datetime) SEBAGAI MaxDateTime, pemain, sumber daya DARI topten GROUP BY home Apakah saya melewatkan sesuatu?
sumber
expected
output dalam versi MySQL 5.6 danbefore
dan saya sangat meragukannya untuk berperilaku sebaliknya dalam versi MySQL 5.7 danafter
.Coba ini
Salam K
sumber
max(datetime)
isdatetime
. Tidak akan membuat masalah?datetime
dipilih?ini permintaan yang Anda butuhkan:
sumber
@Michae Jawaban yang diterima akan berfungsi dengan baik di sebagian besar kasus tetapi gagal untuk satu seperti di bawah ini.
Jika ada 2 baris yang memiliki HomeID dan Datetime yang sama, kueri akan mengembalikan kedua baris, bukan HomeID yang berbeda seperti yang diperlukan, untuk itu tambahkan Perbedaan dalam kueri seperti di bawah ini.
sumber
Berharap query di bawah ini akan memberikan output yang diinginkan:
sumber