Para empezar:No,
SELECT user_id, MAX(salary) FROM users;
no cumple con los estándares. Está utilizando una función agregada (MAX
) sin un GROUP BY
cláusula. Al hacerlo, le dice al DBMS que agregue todos los registros a una sola fila de resultados. Ahora, ¿qué le dice al DBMS que muestre en esta fila de resultados? El salario máximo que se encuentra en la tabla (MAX(salary)
) y el user_id
. Sin embargo, no hay el user_id
; posiblemente hay muchos user_id
diferentes en la mesa. Esto viola el estándar SQL. MySQL se toma la libertad de interpretar el user_id
no agregado como cualquiera user_id
(elegido arbitrariamente).
Entonces, aunque la consulta se ejecuta, el resultado generalmente no es el deseado.
Esta consulta:
SELECT user_id, name, MAX(salary) FROM users GROUP BY user_id;
por otro lado, cumple con los estándares. Veamos de nuevo qué hace esta consulta:esta vez hay un GROUP BY
cláusula que le dice al DBMS que desea una fila de resultados por user_id
. Para cada user_id
quieres mostrar:el user_id
, el name
, y el salary
máximo . Todas estas son expresiones válidas; el user_id
es el user_id
en sí mismo, el name es el único nombre de usuario asociado con el user_id
, y el salary
máximo es el salario máximo del usuario. La columna no agregada name
está permitido, porque depende funcionalmente del agrupado por user_id
. Sin embargo, muchos DBMS no admiten esto, ya que puede ser extremadamente complicado determinar si una expresión depende funcionalmente del grupo o no.
En cuanto a cómo mostrar el registro de usuario con el salario máximo, necesita una cláusula limitante. MySQL proporciona LIMIT
para esto, que puede obtener las primeras n filas. Sin embargo, no se ocupa de las ataduras.
SELECT * FROM users ORDER BY salary DESC LIMIT 1;
es
SELECT * FROM users ORDER BY salary FETCH FIRST ROW ONLY;
en SQL estándar.
Sin embargo, para tratar los vínculos, como en
SELECT * FROM users ORDER BY salary FETCH FIRST ROW WITH TIES;
necesita una subconsulta en MySQL, porque LIMIT
no es compatible con esto:
SELECT * FROM users WHERE salary = (SELECT MAX(salary) FROM users);