Volver a la lista de artículos Artículos
Lectura de 11 minutos

Cómo utilizar GROUP BY y ORDER BY en la misma consulta: Una Guía Detallada

Desenredando cómo usar dos cláusulas SQL básicas - GROUP BY y ORDER BY - en una consulta.

GROUP BY y ORDER BY son cláusulas básicas de SQL. Como tales, se enseñan relativamente pronto en el proceso de aprendizaje. Y normalmente no suponen un gran obstáculo para los principiantes. Sin embargo, el uso conjunto de GROUP BY y ORDER BY puede resultar confuso. Al final de este artículo, tu confusión sobre este tema desaparecerá.

Si quieres practicar el uso de GROUP BY con ORDER BY, nuestro curso interactivo SQL para principiantes interactivo te ayudará. Como su nombre indica, cubre los conceptos básicos de SQL. Facilita el seguimiento de los temas que vamos a presentar en el artículo.

El curso en sí tiene 129 ejercicios para practicar los conceptos básicos de SQL. Estos conceptos incluyen sacar datos de una o múltiples tablas (JOINs) y filtrar datos usando WHERE y operadores como LIKE, ILIKE, IN, y BETWEEN. Por supuesto, GROUP BY está ahí, al igual que las operaciones de conjunto UNION, INTERSECT, y EXCEPT.

¿Qué son GROUP BY y ORDER BY en SQL?

GROUP BY y ORDER BY no son lo mismo - ¡eso es obvio!

La cláusula GROUP BY de SQL agrupa filas de datos con los mismos valores en las columnas especificadas. Esta cláusula se utiliza normalmente con las funciones de agregación de SQL para calcular estadísticas (como el recuento de determinados valores, la suma, la media y el valor mínimo/máximo de un conjunto) para un grupo de filas. He aquí un ejemplo sencillo:

SELECT 
  country,
  COUNT(*)
FROM box_office
GROUP BY country;

La consulta pide a la base de datos que agrupe los datos por los valores de la columna country. A continuación, muestra el nombre del país y cuenta las filas. Esto nos dirá cuántos registros de la tabla pertenecen a cada país.

Hablemos ahora de ORDER BY. Este comando ordena la salida de la consulta en orden ascendente (de 1 a 10, de A a Z) o descendente (de 10 a 1, de Z a A). La ordenación ascendente es la predeterminada; si omite la palabra clave ASCending o DESCending, la consulta se ordenará en orden ascendente. Puede especificar el orden de clasificación utilizando ASC o DESC. He aquí un ejemplo sencillo:

SELECT 
  movie,
  city,
  gross
FROM box_office
ORDER BY gross;

Esta consulta selecciona el nombre de la película, la ciudad en la que se proyecta y los ingresos brutos. A continuación, el resultado se ordena por ingresos brutos utilizando la cláusula ORDER BY.

Esto es algo que probablemente ya sepas. Ahora, veamos como estas cláusulas SQL pueden ser usadas juntas. Puede ser útil tener a mano este artículo sobre cómo funciona GROUP BY o la guía sobre ORDER BY, por si necesitas alguna aclaración sobre algo de lo que mencionamos en este artículo.

Ejemplo de Datos

Utilizaremos una tabla llamada box_office en los siguientes ejemplos. Puedes crearla usando esta consulta.

idmoviecitycountrygross
1Beau Is AfraidAmsterdamNetherlands483,754.22
2The French DispatchValenciaSpain385,741.59
3Beau Is AfraidValenciaSpain40,874.59
4The French DispatchMadridSpain845,125.98
5Beau Is AfraidRotterdamNetherlands352,147.77
6The French DispatchDen HaagNetherlands100,524.14
7Beau Is AfraidMadridSpain147,874.56
8The French DispatchBarcelonaSpain354,789.52
9Beau Is AfraidDen HaagNetherlands208,471.52
10The French DispatchAmsterdamNetherlands408,974.56
11Beau Is AfraidBarcelonaSpain205,487.23
12The French DispatchRotterdamNetherlands236,974.54

Se trata de un resumen de los ingresos en taquilla de dos películas: 'Beau Is Afraid' y 'The French Dispatch'.

Los datos muestran los ingresos (en dólares estadounidenses) de los cines de dos países -España y Países Bajos- y sus respectivas ciudades: Amsterdam, Rotterdam, Den Haag, Barcelona, Madrid y Valencia.

Agrupar por y ordenar por una columna no agregada en SELECT

Empecemos con el ejemplo más sencillo de utilizar GROUP BY y ORDER BY en una consulta. Queremos mostrar la lista de películas en orden alfabético.

He aquí cómo agrupar por una columna y ordenar el resultado por una columna:

SELECT movie
FROM box_office
GROUP BY movie
ORDER BY movie ASC; 

La consulta selecciona el nombre de la película de la tabla box_office. A continuación, tenemos que utilizar GROUP BY. Sin eso, la salida serían las doce filas de la tabla, mostrando los nombres repetidos de las mismas dos películas de la tabla box_office. Queremos que cada película aparezca sólo una vez, ya que éste es el objetivo de la lista. La agrupación de datos se realiza simplemente especificando la columna por la que se desea agrupar en la cláusula GROUP BY.

La salida se ordena mediante la cláusula ORDER BY. Al igual que con GROUP BY, especificamos el nombre de la columna en la cláusula. Queremos que la salida se ordene alfabéticamente, por lo que el nombre de la columna va seguido de ASC.

Utilicemos esta imagen del orden de ejecución de la consulta SQL para visualizar cómo la base de datos llega al resultado.

GROUP BY y ORDER BY en la misma consulta

La consulta primero obtiene la tabla en la cláusula FROM. A continuación, agrupa los datos según la columna especificada en GROUP BY. Después, selecciona la columna en la sentencia SELECT. Y sólo después de todo esto, la salida se ordena según la cláusula ORDER BY.

En otras palabras, primero se agrupan los datos y luego se ordenan. Esto nos lleva a una nota importante: Cuando se utiliza tanto GROUP BY como ORDER BY en una consulta, GROUP BY debe escribirse siempre, sin excepción, antes de ORDER BY.

Veamos el resultado de la consulta.

movie
Beau Is Afraid
The French Dispatch

Como puedes ver, es una lista que muestra nuestras dos películas en orden alfabético.

GROUP BY y ORDER BY una columna agregada en SELECT

Puede utilizar GROUP BY junto con ORDER BY cuando ordene por una función agregada mostrada en SELECT. He aquí un ejemplo:

SELECT 
  movie,
  SUM(gross) AS gross_per_movie
FROM box_office
GROUP BY movie
ORDER BY gross_per_movie DESC;

La consulta selecciona una película de la tabla. A continuación utilizamos la función agregada SUM() para sumar los ingresos brutos de la película. Como queremos mostrar los ingresos brutos por película, tenemos que agrupar el resultado por nombre de película. Como paso final, queremos ordenar los resultados de mayor a menor ganancia. Podemos hacerlo listando la columna agregada en ORDER BY. Esto debe ir seguido de la palabra clave DESC para ordenar de mayor a menor.

Observe que utilizamos el alias gross_per_movie para la columna agregada en ORDER BY. También podríamos haber utilizado la expresión agregada completa:

SELECT 
  movie,
  SUM(gross) AS gross_per_movie
FROM box_office
GROUP BY movie
ORDER BY SUM(gross) DESC;

Este es el resultado:

moviegross_per_movie
The French Dispatch2,332,130.33
Beau Is Afraid1,438,609.89

Muestra dos películas y sus ganancias en orden descendente.

Agrupar por y ordenar por una columna no agregada no en SELECT

En el primer ejemplo, ordenamos la salida por la columna mostrada en SELECT. Intentemos ahora ordenar los datos por una columna que no está en SELECT:

SELECT SUM(gross) AS gross_by_city
FROM box_office
GROUP BY city
ORDER BY city ASC;

En esta consulta, utilizamos la función SUM() para calcular los ingresos brutos por ciudad. Sin embargo, no hay ninguna columna de ciudad en SELECT. Esto se debe a que sólo queremos ver los valores brutos. Seguimos agrupando los resultados por ciudad, del mismo modo que lo haríamos si esta columna estuviera en SELECT. Por último, ordenamos los resultados alfabéticamente por ciudad.

El resultado se muestra a continuación:

gross_by_city
892,728.78
560,276.75
308,995.66
993,000.54
589,122.31
426,616.18

Como puede ver, la consulta funciona. Recuerde: Puede ordenar la salida por una columna no agregada que no aparezca en SELECT - pero sólo si esa columna aparece en GROUP BY.

Esto significa que los datos también pueden agruparse por una columna no mostrada en SELECT. ¿Puede la columna aparecer en SELECT pero no en GROUP BY? No. Debe recordar esta regla: si la columna no agrupada aparece en SELECTtambién debe aparecer en GROUP BY.

GROUP BY Y ORDER BY una columna no agregada en SELECT

Modifiquemos un poco el ejemplo anterior e intentemos ordenar los datos por una columna agregada que no aparece en SELECT.

Este es el código. Intenta mostrar una lista de ciudades ordenadas por ingresos brutos:

SELECT city
FROM box_office
GROUP BY city
ORDER BY SUM(gross);

Seleccionamos la columna city y agrupamos la salida por ella.

A continuación, utilizamos SUM() en ORDER BY para poder ordenar la salida por los ingresos por ciudad. La ordenación es ascendente.

Veamos si la consulta funciona:

city
Den Haag
Valencia
Barcelona
Rotterdam
Amsterdam
Madrid

¡Sí, funciona! Otra nota: puedes ordenar la salida por una columna agregada que no se muestra en el archivo SELECT.

Agrupar por y ordenar por múltiples columnas

Hasta ahora, hemos agrupado datos por una sola columna. Veamos cómo agrupar datos por más de una columna.

Vamos a mostrar cada ciudad y su país:

SELECT 
  city,
  country,
  AVG(gross) AS average_gross
FROM box_office
GROUP BY city, country
ORDER BY city;

Seleccionamos la ciudad y el país. Después, utilizamos AVG() para calcular los ingresos brutos medios por ciudad. A continuación, listamos las mismas columnas en GROUP BY. Como ya ha aprendido, todas las columnas que aparecen en SELECT deben aparecer también en GROUP BY. Cuando enumeramos varias columnas en GROUP BY, simplemente las separamos con una coma.

Por último, ordenamos los resultados por ciudad en orden ascendente:

citycountryaverage_gross
AmsterdamNetherlands446,364.39
BarcelonaSpain280,138.38
Den HaagNetherlands154,497.83
MadridSpain496,500.27
RotterdamNetherlands294,561.16
ValenciaSpain213,308.09

Esto plantea una pregunta: Si puede GROUP BY varias columnas, ¿puede también ORDER BY más de una columna?

Intentémoslo:

SELECT city,
	 country,
	 AVG(gross) AS average_gross
FROM box_office
GROUP BY city, country
ORDER BY country, city;

El principio es el mismo que en GROUP BY: basta con enumerar las columnas en ORDER BY y separarlas con una coma.

Esto es lo que devuelve la consulta:

citycountryaverage_gross
AmsterdamNetherlands446,364.39
Den HaagNetherlands154,497.83
RotterdamNetherlands294,561.16
BarcelonaSpain280,138.38
MadridSpain496,500.27
ValenciaSpain213,308.09

Sí, la salida está realmente ordenada por el país y luego por cada ciudad dentro del país.

Columna agregada tanto en GROUP BY como en ORDER BY

Hemos probado todas las combinaciones, pero no intentamos GROUP BY y ORDER BY múltiples columnas, de las cuales una es agregada. Intentémoslo:

SELECT 
  city,
  AVG(gross) AS average_gross_by_city
FROM box_office
GROUP BY city, AVG(gross)
ORDER BY city, AVG(gross);

Esta consulta quiere mostrar el promedio de ingresos brutos por ciudad. Listamos la ciudad en SELECT y usamos la función AVG(). Luego agrupamos por ciudad y la columna agregada. Por último, la salida se ordena por la misma columna.

Sin embargo, la única salida que obtenemos es este error.

GROUP BY y ORDER BY en la misma consulta

El mensaje de error significa literalmente lo que dice: las funciones de agregación no están permitidas en GROUP BY. ¿Qué sentido tendría utilizarlas en GROUP BY? La función aggregate agrega los datos a una fila, y GROUP BY no puede hacer nada más con ella.

Uso de GROUP BY con HAVING y ORDER BY

GROUP BY y ORDER BY no son las únicas cláusulas que se pueden utilizar en una consulta - también podemos añadir HAVING.

Inspeccionemos el siguiente código para ver cómo funciona.

SELECT 
  city,
  SUM(gross) AS gross_per_city
FROM box_office
GROUP BY city
HAVING SUM(gross) > 800000
ORDER BY SUM(gross) > 800000 DESC;

Esta consulta debería

  • Devolver las ciudades con ingresos brutos superiores a 800.000 $.
  • Mostrar la cantidad ganada por esa ciudad.
  • Ordenar la salida por ingresos brutos en orden descendente.

Para ello, seleccionamos la columna ciudad y utilizamos la función SUM(). Luego agrupamos la salida por ciudad. A continuación, utilizamos la cláusula HAVING para mostrar sólo las ciudades con ingresos superiores a 800.000 $. Simplemente utilizamos la columna agregada de SELECT y la comparamos con la condición utilizando el operador de comparación ">". A continuación, utilizamos lo mismo en ORDER BY para ordenar la salida de forma descendente.

La regla aquí es: La cláusula HAVING se escribe siempre después de GROUP BY pero antes de ORDER BY.

Puedes volver a ver la imagen del orden de ejecución de consultas SQL para revisar esto. Verá que HAVING se ejecuta después de GROUP BY pero antes de ORDER BY. En otras palabras, primero se agrupan los datos, luego se filtran y finalmente se ordenan.

Este es el resultado de la consulta:

citygross_per_city
Amsterdam892,728.78
Madrid993,000.54

Sólo hay dos ciudades en las que nuestras dos películas ganaron más de 800.000 dólares: Amsterdam y Madrid.

Practica el uso de GROUP BY con ORDER BY

Este artículo te ha enseñado que sí, que GROUP BY y ORDER BY se pueden utilizar en la misma consulta SQL. No sólo eso, sino que pueden utilizarse de múltiples maneras.

En el camino, aprendimos algunas reglas importantes:

  1. GROUP BY viene antes que ORDER BY.
  2. La salida puede ordenarse por una columna no agregada que no aparece en SELECT sólo si la columna aparece en GROUP BY.
  3. Los datos pueden agruparse por la columna no agregada que no aparece en SELECT.
  4. Cualquier columna no agregada que aparezca en SELECT debe aparecer en GROUP BY.
  5. La salida puede ordenarse por una columna agregada que no aparezca en SELECT.
  6. No se permite una columna agregada en GROUP BY.
  7. HAVING aparece después de GROUP BY pero antes de ORDER BY.

Aunque te hayamos explicado estas reglas y sientas que has aprendido algo, esto no es suficiente.

Para retener este conocimiento, necesitas practicar usando GROUP BY y ORDER BY - especialmente al principio de tu viaje en SQL. Practicar SQL significa escribir mucho código. Sólo así podrás consolidar tus conocimientos. Nuestro curso SQL para principiantes ofrece 129 ejercicios prácticos de SQL; ¡eso es mucho espacio para practicar!