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
.