Saltar al contenido

Obtenga registros con el valor máximo para cada grupo de resultados SQL agrupados

Solución:

La solución correcta es:

SELECT o.*
FROM `Persons` o                    # 'o' from 'oldest person in group'
  LEFT JOIN `Persons` b             # 'b' from 'bigger age'
      ON o.Group = b.Group AND o.Age < b.Age
WHERE b.Age is NULL                 # bigger age not found

Cómo funciona:

Coincide con cada fila de o con todas las filas de b teniendo el mismo valor en la columna Group y un valor mayor en la columna Age. Cualquier fila de o no tener el valor máximo de su grupo en columna Age coincidirá con una o más filas de b.

los LEFT JOIN hace que coincida con la persona de mayor edad del grupo (incluidas las personas que están solas en su grupo) con una fila llena de NULLs de b (‘sin mayor edad en el grupo’).
Utilizando INNER JOIN hace que estas filas no coincidan y se ignoren.

los WHERE cláusula mantiene solo las filas que tienen NULLs en los campos extraídos de b. Son las personas mayores de cada grupo.

Lecturas adicionales

Esta solución y muchas otras se explican en el libro. Antipatrones SQL: evitar las trampas de la programación de bases de datos

Hay una forma súper simple de hacer esto en mysql:

select * 
from (select * from mytable order by `Group`, age desc, Person) x
group by `Group`

Esto funciona porque en mysql puedes no columnas agregadas no agrupadas, en cuyo caso mysql solo devuelve el primero hilera. La solución es ordenar primero los datos de modo que para cada grupo la fila que desee sea la primera, luego agrupar por las columnas para las que desea el valor.

Evita subconsultas complicadas que intentan encontrar el max() etc., y también los problemas de devolver múltiples filas cuando hay más de una con el mismo valor máximo (como lo harían las otras respuestas)

Nota: Esto es un solo mysql solución. Todas las demás bases de datos que conozco arrojarán un error de sintaxis SQL con el mensaje “las columnas no agregadas no se enumeran en la cláusula group by” o similar. Porque esta solución usa indocumentado comportamiento, los más cautelosos pueden querer incluir una prueba para afirmar que permanece funcionando en caso de que una versión futura de MySQL cambie este comportamiento.

Actualización de la versión 5.7:

Desde la versión 5.7, el sql-mode el entorno incluye ONLY_FULL_GROUP_BY de forma predeterminada, por lo que para que esto funcione debe no tener esta opción (edite el archivo de opciones para que el servidor elimine esta configuración).

Puede unirse a una subconsulta que extrae el MAX(Group) y Age. Este método es portátil en la mayoría de RDBMS.

SELECT t1.*
FROM yourTable t1
INNER JOIN
(
    SELECT `Group`, MAX(Age) AS max_age
    FROM yourTable
    GROUP BY `Group`
) t2
    ON t1.`Group` = t2.`Group` AND t1.Age = t2.max_age;
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *