Na początek:Nie,
SELECT user_id, MAX(salary) FROM users;
nie jest zgodny z normami. Używasz funkcji agregującej (MAX
) bez GROUP BY
klauzula. W ten sposób każesz SZBD agregować wszystkie rekordy w jednym wierszu wyników. Co teraz każesz systemowi DBMS pokazać w tym wierszu wyników? Maksymalna pensja znaleziona w tabeli (MAX(salary)
) i user_id
. Jednak nie ma tego user_id
; prawdopodobnie istnieje wiele różnych user_id
na stole. Narusza to standard SQL. MySQL pozwala sobie na interpretację niezagregowanego user_id
jako dowolny user_id
(dowolny wybór).
Więc nawet jeśli zapytanie jest uruchomione, jego wynik zwykle nie jest pożądany.
To zapytanie:
SELECT user_id, name, MAX(salary) FROM users GROUP BY user_id;
z drugiej strony jest zgodny z normami. Zobaczmy jeszcze raz, co robi to zapytanie:tym razem istnieje GROUP BY
klauzula mówiąca DBMS, że chcesz jeden wiersz wyników na user_id
. Dla każdego user_id
chcesz pokazać:ten user_id
, name
, a maksymalna salary
. Wszystko to są poprawne wyrażenia; na user_id
to user_id
sam, ten name to jedyna nazwa użytkownika powiązana z user_id
, a maksymalna salary
to maksymalna pensja użytkownika. Niezagregowana kolumna name
jest dozwolony, ponieważ jest funkcjonalnie zależny od pogrupowanego według user_id
. Jednak wiele DBMS tego nie obsługuje, ponieważ określenie, czy wyrażenie jest funkcjonalnie zależne od grupy, czy nie, może być niezwykle skomplikowane.
Co do tego, jak pokazać rekord użytkownika z maksymalną pensją, potrzebujesz klauzuli ograniczającej. MySQL zapewnia LIMIT
w tym celu, co może dać ci pierwsze n wierszy. Nie zajmuje się jednak remisami.
SELECT * FROM users ORDER BY salary DESC LIMIT 1;
jest
SELECT * FROM users ORDER BY salary FETCH FIRST ROW ONLY;
w standardowym SQL.
Jednak aby poradzić sobie z remisami, jak w
SELECT * FROM users ORDER BY salary FETCH FIRST ROW WITH TIES;
potrzebujesz podzapytania w MySQL, ponieważ LIMIT
nie obsługuje tego:
SELECT * FROM users WHERE salary = (SELECT MAX(salary) FROM users);