Mój stół to:
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
Muszę wybrać każde odrębne home
posiadające maksymalną wartość datetime
.
Wynik byłby:
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
Próbowałem:
-- 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
Nie działa Zestaw wyników ma 130 wierszy, chociaż baza danych zawiera 187. Wynik zawiera kilka duplikatów 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
Nie. Daje wszystkie rekordy.
-- 3 ..something exotic:
Z różnymi wynikami.
id
,player
aresource
dla wiersza innego niż maksymalny dla danego domu, tj. Dla domu = 10, możesz otrzymać:3 | 10 | 04/03/2009 | john | 300
Innymi słowy, nie gwarantuje, że cała kolumna wiersza w zestawie wyników będzie należała do maks. (data / godzina) dla danego domu.Najszybsze
MySQL
rozwiązanie, bez wewnętrznych zapytań i bezGROUP BY
:Objaśnienie :
Połącz ze sobą tabelę za pomocą
home
kolumny. ZastosowanieLEFT JOIN
zapewnia, że wszystkie wiersze z tabelim
pojawią się w zestawie wyników. Te, które nie mają dopasowania w tabeli,b
będą miałyNULL
s dla kolumnb
.Drugi warunek w
JOIN
pytaniu o dopasowanie tylko wierszy zb
tego ma większą wartość wdatetime
kolumnie niż wiersz zm
.Korzystając z danych opublikowanych w pytaniu,
LEFT JOIN
utworzą następujące pary:Wreszcie
WHERE
klauzula zachowuje tylko pary, które mająNULL
s w kolumnachb
(są oznaczone symbolem*
w powyższej tabeli); oznacza to, że z powodu drugiego warunku zJOIN
klauzuli wybrany wierszm
ma największą wartość w kolumniedatetime
.Przeczytaj książkę Antypatterns SQL: unikanie pułapek związanych z programowaniem baz danych w celu uzyskania innych wskazówek SQL.
źródło
SQLite
pierwszym jest znacznie wolniejszy niż wersja La Voie, gdy nie ma indeksu w dopasowanej kolumnie (tj. „Home”). (Testowane z 24 tys. Rzędów, co daje 13 tys. Rzędów)home
idatetime
adatetime
jest maksymalna dla tego konkretnegohome
?ON
klauzuli. Fe... ON ... AND m.id < b.id
utrzymać najnowszego wpisu (jednej z największychid
), gdy dwa wiersze mają takie same wartości whome
idatetime
kolumny i to jest maksymalnadatetime
.Oto wersja T-SQL :
EDYCJA
Niestety w MySQL nie ma funkcji RANK () OVER.
Ale można go emulować, patrz: Emulowanie funkcji analitycznych (ranking AKA) za pomocą MySQL .
To jest wersja MySQL :
źródło
Działa to nawet, jeśli masz dwa lub więcej wierszy dla każdego
home
z równymiDATETIME
:źródło
WHERE ti.home = t1.home
- czy możesz wyjaśnić składnię?select
Kwerenda zawierająca wierszWHERE ti.home = t1.home
nie potrzebujeFROM
zdefiniowanej klauzulit1
. Jak więc się go stosuje?Myślę, że da to pożądany efekt:
ALE jeśli potrzebujesz również innych kolumn, po prostu połącz z oryginalną tabelą (sprawdź
Michael La Voie
odpowiedź)Z poważaniem.
źródło
Ponieważ ludzie wydają się ciągle napotykać ten wątek (data komentarza wynosi od 1,5 roku), nie jest to o wiele prostsze:
SELECT * FROM (SELECT * FROM topten ORDER BY datetime DESC) tmp GROUP BY home
Żadne funkcje agregujące nie są potrzebne ...
Twoje zdrowie.
źródło
Możesz także wypróbować ten, a w przypadku dużych tabel wydajność zapytań będzie lepsza. Działa, gdy nie ma więcej niż dwóch zapisów dla każdego domu, a ich daty są różne. Lepsze ogólne zapytanie MySQL pochodzi od powyższego Michaela La Voie.
Lub spróbuj Postgres lub dbs, które zapewniają funkcje analityczne
źródło
SQLite
pierwszym jest znacznie wolniejszy niż wersja La Voie, gdy nie ma indeksu w dopasowanej kolumnie (tj. „Home”).Działa to na Oracle:
źródło
źródło
Wypróbuj to dla SQL Server:
źródło
źródło
Oto wersja MySQL, która drukuje tylko jeden wpis, w którym są duplikaty MAX (datetime) w grupie.
Możesz przetestować tutaj http://www.sqlfiddle.com/#!2/0a4ae/1
Przykładowe dane
Wersja MySQL ze zmienną użytkownika
Outout zaakceptowanych odpowiedzi
źródło
Innym sposobem na gt najnowszy wiersz na grupę za pomocą zapytania podrzędnego, które zasadniczo oblicza pozycję dla każdego wiersza na grupę, a następnie odfiltrowuje ostatnie wiersze, jak w przypadku rankingu = 1
PRÓBNY
Oto wizualne demo rangi nr dla każdego rzędu dla lepszego zrozumienia
Powyższe zapytanie zakończy się niepowodzeniem i zwróci więcej niż 1 wiersz dla powyższej sytuacji. Aby zatuszować tę sytuację, potrzebne będą inne kryteria / parametry / kolumny, aby zdecydować, który wiersz należy wziąć, który przypada w powyższej sytuacji. Przeglądając przykładowy zestaw danych, zakładam, że istnieje kolumna klucza podstawowego,
id
którą należy ustawić na automatyczne zwiększenie. Możemy więc użyć tej kolumny, aby wybrać najnowszy wiersz, dostosowując to samo zapytanie za pomocąCASE
instrukcji typuPRÓBNY
Powyższe zapytanie spowoduje wybranie wiersza o najwyższym identyfikatorze spośród tych samych
datetime
wartościdemo wizualne rangi nr dla każdego rzędu
źródło
Dlaczego nie użyć: WYBIERZ dom, MAX (data / godzina) AS MaxDateTime, odtwarzacz, zasób Z topten GROUP BY home Czy coś przeoczyłem?
źródło
expected
wyniku w MySQL w wersji 5.6 ibefore
bardzo wątpię, aby zachowało się inaczej w MySQL w wersji 5.7 iafter
.Spróbuj tego
Pozdrawiam K.
źródło
max(datetime)
todatetime
. Czy to nie będzie stanowiło problemu?datetime
wybierany jest najwyższy ?oto zapytanie, którego potrzebujesz:
źródło
@Michae Przyjęta odpowiedź będzie działać dobrze w większości przypadków, ale nie powiedzie się dla jednego z poniższych.
W przypadku, gdy były dwa wiersze o Identyfikatorze domowym i Datetime takie same, zapytanie zwróci oba wiersze, a nie odrębny Identyfikator domowy zgodnie z wymaganiami, dla dodania Wyraźny w zapytaniu, jak poniżej.
źródło
Nadzieja poniżej zapytania da pożądany wynik:
źródło