Per cominciare:No,
SELECT user_id, MAX(salary) FROM users;
non è conforme agli standard. Stai utilizzando una funzione aggregata (MAX
) senza un GROUP BY
clausola. In questo modo dici al DBMS di aggregare tutti i record in un'unica riga di risultati. Ora cosa dici al DBMS di mostrare in questa riga dei risultati? Lo stipendio massimo trovato nella tabella (MAX(salary)
) e il user_id
. Tuttavia, non esiste il il user_id
; ci sono probabilmente molti user_id
differenti sul tavolo. Ciò viola lo standard SQL. MySQL si prende la libertà di interpretare il user_id
non aggregato come qualsiasi user_id
(scelto arbitrariamente).
Quindi, anche se la query viene eseguita, il risultato di solito non è quello desiderato.
Questa domanda:
SELECT user_id, name, MAX(salary) FROM users GROUP BY user_id;
dall'altro è conforme agli standard. Vediamo di nuovo cosa fa questa query:questa volta c'è un GROUP BY
clausola che dice al DBMS che vuoi una riga di risultato per user_id
. Per ogni user_id
vuoi mostrare:il user_id
, il name
e il massimo salary
. Tutte queste sono espressioni valide; il user_id
è il user_id
stesso, il name è l'unico nome utente associato a user_id
e il massimo salary
è lo stipendio massimo dell'utente. La colonna non aggregata name
è consentito, perché dipende funzionalmente dal raggruppato per user_id
. Molti DBMS non lo supportano, tuttavia, perché può diventare estremamente complicato determinare se un'espressione dipende funzionalmente dal gruppo o meno.
Per quanto riguarda come mostrare il record utente con lo stipendio massimo, è necessaria una clausola limitativa. MySQL fornisce LIMIT
per questo, che può farti ottenere le prime n righe. Non si tratta però di cravatte.
SELECT * FROM users ORDER BY salary DESC LIMIT 1;
è
SELECT * FROM users ORDER BY salary FETCH FIRST ROW ONLY;
in SQL standard.
Per affrontare i pareggi, invece, come in
SELECT * FROM users ORDER BY salary FETCH FIRST ROW WITH TIES;
hai bisogno di una sottoquery in MySQL, perché LIMIT
non supporta questo:
SELECT * FROM users WHERE salary = (SELECT MAX(salary) FROM users);