Los listados de registros son una forma habitual de presentar los datos extraídos de las tablas de las bases de datos, pero en el momento en que necesitamos evaluar campos numéricos en forma de sumas, contabilizaciones, medias o cualquier otro parámetro matemático o estadístico, se hace necesario las funciones de agregación.
El comando GROUP BY, combinado con funciones, permite presentar información resumida y concisa en cualquier informe.
Este post forma parte del Tutorial básico de SQL Server cuyo índice completo puedes ver aquí: Tutorial básico de SQL Server
Empecemos con una breve introducción a las funciones. En el anterior post ya vimos algunas funciones pero en esa ocasión eran relativas a tipos de datos alfanuméricos como REPLACE, LTRIM, RTRIM, etc.
Ahora, vamos a ver algunos ejemplos de funciones para tipos numéricos:
SUM permite averiguar el sumatorio de todos los datos de un campo numérico en una extracción realizada por SELECT. La sintaxis para esta función y, en general para todas, es simple SUM(<campo>).
Por ejemplo en nuestra tabla Clientes podemos obtener el siguiente dato total:
SELECT sum(edad)
FROM [Primera].[dbo].[Clientes]
En la pestaña Resultados tendremos la suma de todas las edades los clientes. ¿La suma de las edades? ¿No es muy útil no?. Por supuesto, pero T-SQL tiene funciones para todo; por ejemplo, tiene mas sentido hallar una media y la función es AVG.
SELECT avg(edad)
FROM [Primera].[dbo].[Clientes]
Esto nos dará un dato mas útil: la edad media de nuestra clientela.
No podemos dejar de mencionar la función COUNT, muy utilizada. Contabiliza el número de datos del campo especificado (o todos los registros si ponemos *).
SELECT count(*) AS TIENE_CUENTA
FROM [Primera].[dbo].[Clientes]
WHERE Cuenta = 1
Rápidamente obtenemos el número de clientes con cuenta en nuestro negocio. El filtro contrario con 0 o null nos indicará el número total de aquellos que no tiene cuenta.
¿Pero que ocurre si necesitamos esos dos datos en forma de resultados tabulados?. Aquí es donde interviene la clausula GROUP BY. Permite agrupar por un determinado campo los subtotales o totales obtenidos a partir de otro. Retomemos el ejemplo anterior:
Deseamos contabilizar dos subtotales: por un lado los clientes que tienen cuenta y los que no, el código sería:
SELECT count(*) AS NUM_CLIENTES, Cuenta
FROM [Primera].[dbo].[Clientes]
GROUP BY Cuenta
Este resultado nos presenta rápidamente y de forma clara una distribución de las tres posibles agrupaciones: indeterminado, sin cuenta y con cuenta:

Si tenemos que presentarlo mas tipo informe, CASE , que lo vimos de pasada en el anterior post, puede ayudar:
SELECT case when Cuenta = 0 then 'Sin cuenta'
when Cuenta = 1 then 'Con cuenta'
else 'No determinado' end AS Tipo,
count(nombre) AS 'Nº Clientes'
FROM [Primera].[dbo].[Clientes]
GROUP BY Cuenta

Y este es el aspecto con Resultados a texto (CTRL + T):

Github Copilot
También sería muy interesante ordenar por tramos de edad, es decir lo típico de averiguar cual es el rango de edad mas numeroso de nuestros clientes. Interviene de nuevo el CASE:
...
CASE
WHEN edad BETWEEN 10 AND 20 THEN '10-20'
WHEN edad BETWEEN 21 AND 30 THEN '21-30'
WHEN edad BETWEEN 31 AND 40 THEN '31-40'
...
Así todos los tramos, después agruparemos para contabilizar por cada tramo.
Evidentemente es demasiado teclear; mejor que trabaje Copilot mediante el siguiente prompt:
Realiza un script para que en la tabla clientes se agrupe el numero de clientes por tramos de edad: 10 a 20, de 21 a 30, de 31 a 40 etc.
Y en mi caso el resultado fué correcto:

El CASE contempla todas las posibilidades de rango de edad (la palabra ELSE es siempre fundamental). Como luego hace una agrupación con la función COUNT; en la clausula GROUP BY se debe poner todo lo especificado en 'RangoEdad'.
Un script "pesado de escribir". Evidentemente hemos hecho bien en que lo realizase Copilot.
Finalmente ordena mediante otra función MIN(edad) es decir de menor a mayor rango.
Y de momento nada más, esto ha sido una breve visión de las posibilidades de agrupación.
Seguimos en el siguiente post.