sql >> Base de Datos >  >> RDS >> Database

Cómo seleccionar la primera fila en cada grupo GROUP BY

Problema:

Has agrupado tus datos con GROUP BY y me gustaría mostrar solo la primera fila de cada grupo.

Ejemplo:

Nuestra base de datos tiene una tabla llamada exam_results con datos en la siguiente tabla:

nombre apellido año resultado
Juan Klein 2020 40
Edith Negro 2020 43
Marcar Johnson 2019 32
Laura Verano 2020 35
Kate Smith 2019 41
Jacob Negro 2019 44
Tomás Bennett 2020 38
Emily Kelly 2020 43

Para cada año, busquemos al alumno con el mejor result . Si hay dos estudiantes empatados como los mejores en un grupo, seleccionaremos arbitrariamente a uno de ellos para mostrarlo.

Solución:

WITH added_row_number AS (
  SELECT
    *,
    ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
  FROM exam_results
)
SELECT
  *
FROM added_row_number
WHERE row_number = 1;

El resultado es:

nombre apellido año resultado número_de_fila
Jacob Negro 2019 44 1
Emily Kelly 2020 43 1

Discusión:

Primero, debe escribir un CTE en el que asigne un número a cada fila dentro de cada grupo. Para hacer eso, puede usar el ROW_NUMBER() función. En OVER() , especifica los grupos en los que se deben dividir las filas (PARTITION BY ) y el orden en que se deben asignar los números a las filas (ORDER BY ).

Eche un vistazo al resultado de la consulta interna:

SELECT
  *,
  ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
FROM exam_results;
nombre apellido año resultado número_de_fila
Jacob Negro 2019 44 1
Kate Smith 2019 41 2
Marcar Johnson 2019 32 3
Emily Kelly 2020 43 1
Edith Negro 2020 43 2
Juan Klein 2020 40 3
Tomás Bennett 2020 38 4
Laura Verano 2020 35 5

Asigne los números de fila dentro de cada grupo (es decir, año). Cada fila tiene un número de fila basado en el valor del result columna. Las filas se ordenan en orden descendente debido a DESC palabra clave después de ORDER BY result . Incluso si hay varias filas dentro de un grupo que tienen el mismo valor de result , las filas todavía reciben números diferentes. Aquí, Edith Black y Emily Kelly tienen el mismo result pero diferentes números de fila. Para cambiar este comportamiento y asignar el mismo número de fila para el mismo resultado dentro de un grupo, use RANK() o DENSE_RANK() en lugar de ROW_NUMBER() .

En la consulta externa, selecciona todos los datos del CTE (added_row_number ) y use un WHERE condición para especificar qué fila mostrar de cada grupo. Aquí, queremos mostrar la primera fila, por lo que la condición es row_number = 1 .

Tenga en cuenta que puede modificar fácilmente la solución para obtener, por ejemplo, la segunda fila de cada grupo.

WITH added_row_number AS (
  SELECT
    *,
    ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
  FROM exam_results
)
SELECT
  *
FROM added_row_number
WHERE row_number = 2;

Aquí está el resultado:

nombre apellido año resultado número_de_fila
Kate Smith 2019 41 2
Edith Negro 2020 43 2

Por otro lado, si desea obtener las filas con el segundo valor más alto de result dentro de cada grupo, debe usar DENSE_RANK() función. Mientras que el ROW_NUMBER() La función crea números consecutivos para cada fila en un grupo, dando como resultado diferentes valores asignados a las filas con el mismo resultado, el DENSE_RANK() función da el mismo número a las filas con el mismo resultado.

WITH added_dense_rank AS (
  SELECT
    *,
    DENSE_RANK() OVER(PARTITION BY year ORDER BY result DESC) AS rank
  FROM exam_results
)
SELECT
  *
FROM added_dense_rank
WHERE rank = 2;
nombre apellido año resultado rango
Kate Smith 2019 41 2
Juan Klein 2020 40 2

Puede ver que John Klein tiene el segundo valor más alto de result (40) para el año 2020. John Klein es en realidad la tercera persona del grupo, pero los dos primeros estudiantes tienen el mismo result y ambos tienen rank = 1 .