Mam tabelę („lms_attendance”) z czasami zameldowania i wymeldowania użytkowników, która wygląda następująco:
id user time io (enum)
1 9 1370931202 out
2 9 1370931664 out
3 6 1370932128 out
4 12 1370932128 out
5 12 1370933037 in
Próbuję utworzyć widok tej tabeli, który wyprowadziłby tylko najnowszy rekord na identyfikator użytkownika, jednocześnie dając mi wartość „in” lub „out”, więc coś takiego:
id user time io
2 9 1370931664 out
3 6 1370932128 out
5 12 1370933037 in
Jestem dość blisko, ale zdałem sobie sprawę, że widoki nie akceptują podzapytań, co znacznie utrudnia sprawę. Najbliższe zapytanie, które otrzymałem, brzmiało:
select
`lms_attendance`.`id` AS `id`,
`lms_attendance`.`user` AS `user`,
max(`lms_attendance`.`time`) AS `time`,
`lms_attendance`.`io` AS `io`
from `lms_attendance`
group by
`lms_attendance`.`user`,
`lms_attendance`.`io`
Ale otrzymuję:
id user time io
3 6 1370932128 out
1 9 1370931664 out
5 12 1370933037 in
4 12 1370932128 out
Co jest bliskie, ale nie idealne. Wiem, że ta ostatnia grupa według nie powinna tam być, ale bez niej zwraca ostatni czas, ale nie ze swoją względną wartością we / wy.
Jakieś pomysły? Dzięki!
mysql
sql
greatest-n-per-group
Keith
źródło
źródło
Odpowiedzi:
Pytanie:
SQLFIDDLEExample
Wynik:
Rozwiązanie, które będzie działać za każdym razem:
SQLFIDDLEExample
źródło
Nie ma potrzeby odkrywania na nowo koła, ponieważ jest to powszechny problem z największą liczbą n na grupę . Przedstawiono bardzo ładne rozwiązanie .
Wolę najbardziej uproszczone rozwiązanie ( zobacz SQLFiddle, zaktualizowane Justin's ) bez podzapytań (dzięki czemu jest łatwe w użyciu w widokach):
Działa to również w przypadku, gdy istnieją dwa różne rekordy o tej samej największej wartości w tej samej grupie - dzięki sztuczce z
(t1.time = t2.time AND t1.Id < t2.Id)
. Jedyne, co tutaj robię, to zapewnienie, że w przypadku, gdy dwa rekordy tego samego użytkownika mają ten sam czas, wybierany jest tylko jeden. Właściwie nie ma znaczenia, czy kryteria są,Id
czy coś innego - w zasadzie każde kryterium, które z pewnością są wyjątkowe, sprawdzi się tutaj.źródło
t1.time < t2.time
i minimalne byłybyt1.time > t2.time
przeciwieństwem mojej początkowej intuicji.t1.time < t2.time
warunek ma zastosowanie :-)WHERE t2.user IS NULL
jest trochę dziwne. Jaką rolę odgrywa ta linia?OR (t1.time = t2.time AND t1.Id < t2.Id))
sekcję?Opierając się na odpowiedzi @TMS, podoba mi się to, ponieważ nie ma potrzeby wykonywania podzapytań, ale myślę, że pominięcie
'OR'
części będzie wystarczające i znacznie prostsze do zrozumienia i przeczytania.jeśli nie interesują Cię wiersze z zerowymi czasami, możesz je przefiltrować w
WHERE
klauzuli:źródło
OR
części jest naprawdę złym pomysłem, jeśli dwa rekordy mogą mieć to samotime
.Już rozwiązane, ale tak dla przypomnienia innym podejściem byłoby stworzenie dwóch widoków ...
Kliknij tutaj, aby zobaczyć, jak działa w SQL Fiddle
źródło
źródło
join (select * from lms_attendance ) b
=join lms_attendance b
źródło
Jeśli korzystasz z MySQL 8.0 lub nowszego, możesz używać funkcji okna :
Pytanie:
DBFiddleExample
Wynik:
Zaleta, którą widzę nad zastosowaniem rozwiązania zaproponowanego przez Justina jest to, że umożliwia ono wybranie wiersza z najnowszymi danymi na użytkownika (lub według identyfikatora lub cokolwiek innego) nawet z podzapytań bez potrzeby widoku pośredniego lub tabeli.
A jeśli korzystasz z HANA, jest to również ~ 7 razy szybsze: D
źródło
Ok, może to być hack lub podatność na błędy, ale w jakiś sposób to również działa -
źródło
Spróbuj tego zapytania:
źródło
id
iio
są to kolumny niezagregowane, których nie można użyć w plikugroup by
.Ewentualnie możesz grupować według użytkowników, a następnie porządkować według czasu. Coś jak poniżej
źródło
To zadziałało dla mnie:
źródło