Anuncios en tutorial de programación PLSQL

viernes, 11 de mayo de 2018

Funciones de grupo en SQL (cláusulas GROUP BY y HAVING)

En los ejemplos del artículo anterior se utilizaban las funciones de grupo aplicadas sobre todos los registros seleccionados en un SELECT determinado. Lo cierto es que en muchas ocasiones podemos necesitar categorizar las agrupaciones dentro de un conjunto de datos.

Funciones de grupo en SQL (cláusulas GROUP BY y HAVING)

Cláusula GROUP BY


La cláusula GROUP BY permite recolectar los datos dentro de un SELECT y agrupar los resultados por una o más columnas. Es decir, las funciones de grupo y la cláusula GROUP BY se utilizan conjuntamente para calcular los valores que arrojan dichas funciones para cada uno de los grupos.

En el ejemplo que vemos a continuación, la consulta devuelve el número total de compras y los costes de compra acumulados por proveedor:
SELECT proveedor, 
       COUNT(compra_id) num_compras, 
       SUM(coste_compra) coste_total
FROM compras
GROUP BY proveedor
ORDER BY proveedor;

Y una posible salida sería:
PROVEEDOR   NUM_COMPRAS COSTE_TOTAL
----------- ----------- -----------
ACME                135     1245253
TEMPER               12       65483
WRAK                 16        4500
                     20        3000

En la salida se puede observar que existen veinte compras que no tienen asignado ningún proveedor y que han sido incluidas como un grupo en los resultados. En la consulta también hemos añadido una cláusula ORDER BY para ordenar los datos por orden alfabético de proveedor ya que la cláusula GROUP BY no ordena los datos en ningún orden particular. El siguiente ejemplo muestra una posible salida cuando la consulta no incluye la cláusula ORDER BY.
SELECT nombre_proveedor, 
       COUNT(compra_id) num_compras, 
       SUM(coste_compra) coste_total
FROM compras
GROUP BY proveedor;

Y una posible salida sería:
PROVEEDOR   NUM_COMPRAS COSTE_TOTAL
----------- ----------- -----------
TEMPER               12       65483
WRAK                 16        4500
                     17        3000
ACME                135     1245253

Cuando una cláusula GROUP BY viene seguida de una cláusula ORDER BY, las columnas que aparecen en la cláusula ORDER BY deben también estar incluidas en el SELECT. De no estarlo obtendremos un error ORA-00979 durante la ejecución del SELECT.
SELECT nombre_proveedor, 
       COUNT(compra_id) num_compras, 
       SUM(coste_compra) coste_total
FROM compras
GROUP BY nombre_proveedor
ORDER BY proveedor_id;

ORDER BY proveedor_id
         *
ERROR en línea 6:
ORA-00979: no es una expresión GROUP BY

Algo similar ocurrirá si no incluimos en la cláusula GROUP BY todas las columnas que aparecen en el SELECT y que no se corresponden con una función de grupo. En este caso veremos el error ORA-00937.
SELECT nombre_proveedor, proveedor_id,
       COUNT(compra_id) num_compras, 
       SUM(coste_compra) coste_total
FROM compras
GROUP BY nombre_proveedor
ORDER BY nombre_proveedor;

SELECT nombre_proveedor, proveedor_id,
                         *
ERROR en línea 1:
ORA-00937: la función de grupo no es de grupo único

La consulta correcta sería:
SELECT nombre_proveedor, proveedor_id,
       COUNT(compra_id) num_compras, 
       SUM(coste_compra) coste_total
FROM compras
GROUP BY nombre_proveedor, proveedor_id
ORDER BY nombre_proveedor;

Cláusula HAVING


Al igual que una sentencia SELECT puede incluir una cláusula WHERE para que la salida de la consulta solo incluya los registros que cumplen con unos ciertos criterios, la cláusula GROUP BY puede utilizar la cláusula HAVING para hacer algo parecido.

En el siguiente ejemplo utilizamos la cláusula HAVING para que nuestro SELECT solo muestre aquellos proveedores que tienen más de 15 compras y cuyo coste total de las mismas sea superior a 4000 euros.
SELECT proveedor, 
       COUNT(compra_id) num_compras, 
       SUM(coste_compra) coste_total
FROM compras
GROUP BY proveedor
HAVING COUNT(compra_id)> 15 
   AND SUM(coste_compra) > 4000
ORDER BY proveedor;

Y la salida sería:
PROVEEDOR   NUM_COMPRAS COSTE_TOTAL
----------- ----------- -----------
ACME                135     1245253
WRAK                 16        4500

Podemos ver que del listado han desaparecido dos registros, el del proveedor TEMPER que tiene menos de 15 compras y el grupo sin proveedor conocido cuyo coste total es menor de 4000 euros.

Por otro lado, hay que mencionar que la cláusula HAVING puede incluir también límites sobre columnas que no son funciones de grupo. Veamos un ejemplo.
SELECT proveedor, comprador,
       COUNT(compra_id) num_compras, 
       SUM(coste_compra) coste_total
    FROM compras
GROUP BY proveedor, comprador
HAVING COUNT(compra_id)> 15 
   AND SUM(coste_compra) > 4000
   AND comprador LIKE 'P%'
ORDER BY proveedor, comprador;

PROVEEDOR   COMPRADOR NUM_COMPRAS COSTE_TOTAL
----------- --------- ----------- -----------
ACME        Pablo              21       51268
ACME        Pedro             100      834876
WRAK        Pablo              16        4500

La consulta además de limitar la salida a aquellos proveedores que tienen más de 15 compras y cuyo coste total de las mismas sea superior a 4000 euros, ahora solo incluye las compras de los compradores cuyo nombre empieza por 'P'. Ni que decir tiene que esta última condición podría haberse incluido en la cláusula WHERE.

En conclusión, las cláusulas GROUP BY y HAVING son realmente útiles cuando queremos realizar cálculos sobre un grupo de columnas y, a su vez, limitar la salida dependiendo de los valores entregados por dichos cálculos.

1 comentarios:

Peterpoweeer dijo...

Dentro de dos días tengo un examen de esta vaina, espero poder aprobarlo gracias a tí.