Conoce SQL – SELECT – Parte 3 – Agrupaciones
por Maxpowel en abr.29, 2009
En esta tercera parte de select veremos qué son y cómo se usan las agrupaciones de datos.
Vamos a empezar por lo más sencillo. Imagina que queremos contar el numero de filas de una tabla, por ejemplo para saber cuantos usuarios tenemos o el numero de paquetes en nuestra base de datos. Si no se conce como sql nos lo hace, lo normal es tirar por algo de esto desde php:
$sql=”SELECT * FROM paquetes”;
$res=mysql_query($sql);
$n=0;
while ($fila=mysql_fetch_array($res))
{
$n++;
}
echo “Tenemos $n paquetes en la base de datos”;
Quizá a estas alturas ya te hayas percatado (aunque sea porque siempre digo lo mismo
) de lo ineficiente que es este algoritmo. Seleccionamos TODO cuando no nececitamos NADA, no necesitamos ningún dato de la tabla pero sin embargo vamos a ir extrayendo toda la tabla. Para esto existe count, que se usaría de esta manera:
$sql=”SELECT count(*) FROM paquetes”;
$res=mysql_query($sql);
$fila=mysql_fetch_array($res);
echo “Tenemos “.$fila[0].” paquetes en la base de datos”;
A la función count se le pasa el argumento de la columna que queremos contar pero ya te digo que da igual que pongas algo o simplemente el asterisco, mysql hará lo mismo así que ponemos asterisco para evitar tener fallos. En este caso la diferencia es la eficiencia ya que el algoritmo en php no es nada complejo.
Para la siguiente demostración vamos a insertar una columna más a la tabla paquetes. Esta columna contendrá el precio que se ha cobrado por transportar el paquete
ALTER TABLE paquetes ADD precio DOUBLE
Y asignamos precio a los paquetes
UPDATE paquetes SET precio = ’25.30′ WHERE codigo_paquete = ‘MA125′;
UPDATE paquetes SET precio = ’12′ WHERE codigo_paquete = ‘PA123′;
UPDATE paquetes SET precio = ’9.36′ WHERE codigo_paquete = ‘PA124′;
UPDATE paquetes SET precio = ’8.12′ WHERE codigo_paquete = ‘PA125′;
UPDATE paquetes SET precio = ’5.30′ WHERE codigo_paquete = ‘PA129′;
UPDATE paquetes SET precio = ’9.67′ WHERE codigo_paquete = ‘VA126′;
UPDATE paquetes SET precio = ’22.4′ WHERE codigo_paquete = ‘VA127′;
UPDATE paquetes SET precio = ’35′ WHERE codigo_paquete = ‘VA128′;
Ojo con los dobles, aunque sean numeros es recomendable ponerlos entre comillas simples porque si llevan decimales te dará error si no las pones.
Ahora queremos saber lo que ha costado enviar todos los paquetes. En php podríamos hacerlo de esta manera:
$sql=”SELECT precio FROM paquetes”;
$res=mysql_query($sql);
$n=0;
while ($fila=mysql_fetch_array($res))
{
$n+=$fila[0];
}
echo “El precio total es $n”;
Bueno esta solución no está mal del todo pero es mucho mas elegante esta otra
$sql=”SELECT sum(precio) FROM paquetes”;
$res=mysql_query($sql);
$fila=mysql_fetch_array($res);
echo “El precio total es “.$fila[0];
Bien, estas funciones están bien pero se debería de poder hacer algo más complejo para tener una sección solo para ello. Pues si, y ya veras que cachi. Ahora vamos realmente a agrupar datos.
Imagina que queremos saber el numero de paquetes que se han enviado a cada ciudad, la consulta podría ser la siguiente.
SELECT ciudad,count(*) FROM paquetes
JOIN ciudades USING (id_ciudad)
GROUP BY ciudad
Esta consulta ya nos soluciona bastante a que sí. Esta consulta lo que hace es mediante GROUP BY dividir en grupos todos los datos en función a una columna. Es decir, si le decimos que agrupe por ciudad cojerá y hará tantos grupos como ciudades haya y meterá en esos grupos a los paquetes de de esa ciudad.
Lo que hay que tener en cuenta es que al agrupar datos, esos datos solo se pueden manejar como grupos y no individualmente. En resumidas cuentas, solo podemos estraer el dato de la columna que usemos como “agrupador” que en este caso es ciudad y funciones de grupo como son count o sum.
Más o menos la divisió que hace de los grupos sería esta, en el caso de crearlos a partir de la ciudad

Crea tres grupos, uno para cada ciudad. Pero a la información de dentro no se puede acceder individualmente, es decir, no podríamos extraer la descripción ni el código de paquete pero sí contar el numero de elementos del grupo (count) o sumar todos los elemenos de una columna numérica (sum). Para esto hay muchas funciones, otra interesante es AVG que calcula el valor medio pero vamos, que hay muchas.
Ahora se nos a antojado saber con qué ciudad hemos ganado más dinero.
SELECT CONCAT(‘La ciudad con la que mas dinero se ha ganado ha sido ‘,ciudad)
FROM paquetes
JOIN ciudades USING (id_ciudad)
GROUP BY ciudad
ORDER BY SUM(precio) DESC
LIMIT 1
Ala cuantas cosas extrañas tiene esta consulta no? Simplemente quería enseñarte que con SQL puedes hacer de todo. Vamos a explicar la consulta.
CONCAT une tantas cadenas de texto como parámetros se le pasen. En este caso se pasa un string y el valor de la columna ciudad. Despés agrupamos y ordenamos por la suma del precio de cada grupo en descendente (los más altos se muestran primero) y por último limitamos la consulta a un único resultado.
Ahora vamos a usar buena parte de nuestros conocimientos para hacer una consulta que nos diga cuando hemos facturado a partir del 2009.
SELECT SUM(precio) FROM (
SELECT SUM(precio) AS precio FROM paquetes
WHERE fecha_entrega >= ’1/1/2009′
GROUP BY fecha_entrega
) AS tablita
Vamos a comprender la consulta. Usamos la funcion SUM para sumar todos los valores de la columna precio de una tabla, en este caso la tabla no existe realmente asi que “creamos” una mediante un subselect, a la cual le damos el nombre “tablita”. Dentro del subselect se seleccionan de la tabla paquetes que se han entregado el dia 1/1/2009 o más tarde, los agrupamos y sumamos (se podría haber hecho sin agrupar pero así vamos practicando las agrupaciones). Cuando sepas hacer consultas de este tipo se podría decir que conoces bastante bien mysql a nivel conceptual.
La última parte de este capítulo es como comparar dos columnas “agrupadas”. Ejecuta esta consulta:
SELECT SUM(precio) FROM paquetes
WHERE SUM(precio) > 10
GROUP BY precio
Supongo que te da error. Vamos a intentar esto otro
SELECT SUM(precio) FROM paquetes
WHERE precio > 10
GROUP BY precio
Parece que aqui si nos deja, pero no nos vale ya que esta comparando precio individualmente y no como grupo. Vemos que WHERE no funciona, entonces me veo obligado a ensñarte otra palabrita mágina, HAVING.
SELECT SUM(precio) FROM paquetes
GROUP BY precio
HAVING SUM(precio) > 10
!Que bien! esto ya funciona. Cuando queremos realizar alguna comparación de datos agrupados lo que hay que usar es HAVING (que va desupués de GROUP BY evidentemente) en vez de WHERE.
Ahora ya solo queda practicar y practicar para coger habilidad. Si nunca habías leído un manual de SQL te habrás dado cuenta de que una base de datos no sólo guarda datos y con el tiempo te irás dando más cuenta. Los select o mejor dicho el DQL es todo un mundo y la parte mas potente de SQL y por mucho rollo que te haya contado me he dejado muchas cosas en el tintero pero mi objetivo no es hacerte un experto sino ayudarte a dar el primer paso.
Hasta el siguiente capítulo!
Entradas relacionadas:
- Conoce SQL – SELECT – Parte 2 En la primera parte sobre SELECT vimos básicamente como enlazar...
- Conoce SQL – SELECT – Parte 1 Conoce SQL – DQL – Parte 1 Todo lo visto...
- Conoce SQL – Lenguaje procedimental 2 – Funciones El concepto de función de el lenguaje procedimental de mysql...
- Conoce SQL – VIEWS (vistas) Ahora ya sabemos como hacer consultas bastante completas, pero ademas...
- Conoce SQL – Restricciones – FOREIGN KEY 1 – E: Restricción FOREIGN KEY Las foreign key o...





septiembre 16th, 2009 on 4:44 pm
muy bueno xD estuve practicando
septiembre 16th, 2009 on 11:45 pm
las agrupaciones algo muy útil que no todo el mundo conoce. Si tienes algún problema aquí te lo aclararé