Las funciones de agregación no pueden aparecer en el where

Es habitual encontrarse consultas como la siguiente: hallar los artículos con el precio más bajo de entre los contenidos en una tabla. Para resolverla podríamos tener la tentación de ejecutar un select SQL, que incluye funciones de agregación en el where, y, por tanto, es incorrecta:

Notación de comparación de tupla para simplificar consultas

SQL permite comparar varias columnas con una única operación, usando la notación de tupla; p.ej., (nombre, apellido) = ('Fran', 'García'). Se trata de una notación muy compacta y útil, que puede llegar a simplificar mucho algunas consultas que requieren de varias subconsultas sobre la misma tabla. Veamos un ejemplo.

FULL OUTER JOIN en MySQL

A diferencia de otros SGBD como SQL Server, Oracle o PostgreSQL, MySQL no implementa la operación FULL OUTER JOIN (me refiero a la versión 8.0.32 e inferiores). Sí implementa LEFT OUTER JOIN y RIGHT OUTER JOIN.

Para realizar esta operación en MySQL hay que hacer la UNION de ambos OUTER JOIN laterales. Pero la explicación requiere aclarar algún matiz adicional que encontrarás descrito a continuación

En las instrucciones update o delete también se pueden hacer joins

Del mismo modo que ante una consulta que requiera datos de varias tablas recurrimos a join para obtener la solución, en una instrucción update o delete también podemos hacerlo. Lo que sigue utiliza la sintaxis propia de MySQL, pero otros SGBD (como SQL Server o PostgreSQL) también permiten hacerlo de forma similar.

Para actualizar un campo usando su antiguo valor no hace falta una subconsulta

Sabemos que en las instrucciones LMD (insert, update, delete) podemos usar subconsultas. Pero en ocasiones, como cuando se quiere actualizar el valor de un campo a partir del valor anterior del mismo, no es conveniente emplearlas. Lo único que conseguimos es complicar la instrucción y penalizar el rendimiento en su ejecución.

Qué hacer cuando una modificación requiere consultar la tabla que se está modificando

En ocasiones, para modificar una tabla (con update, insert, delete), necesitamos consultar algún dato de la la propia tabla para usarlo en la instrucción de modificación. En MySQL esto no es posible, salvo que emplees este truco.

Ejercicio típico: entidades que se relacionan con dos (o más) entidades de otro tipo

Un tipo de consulta habitual es la que pretende obtener datos de una entidad de un tipo dado (entidad A) que se relacionan con varias (dos o más) de otra entidad de otro tipo (entidad B). P.ej.: alumnos (A) que están matriculados en dos asignaturas (B) dadas, proyectos (A) en los que trabajan al mismo tiempo dos empleados (B) dados, etc.

Todo lo que esté en el having, y que no sean funciones de agregación, debe estar en el group by

En otra lección de este blog (que debes leer aquí antes que ésta) se discute sobre la regla de SQL que obliga a que, en una consulta de agrupación, si se quiere recuperar en el select algún dato (o expresión que use algún dato) que no sea el resultado de una función de agregación, ese dato debe estar en el criterio de agrupación de la cláusula group by. Esa regla también se aplica a la cláusula having: ésta solo puede tener funciones de agregación o campos del criterio de agrupación.

Todo lo que esté en el select, y que no sean funciones de agregación, debe estar en el group by

Cuando se hace una consulta de agrupación, SQL obliga a que todo aquello que se incluya en el select sea alguna de estas tres cosas:

  • campos del criterio de agrupación
  • expresiones que usen campos del criterio de agrupación
  • expresiones con funciones de agregación

En esta lección discutimos sobre esta regla de SQL.

Funciones de manipulación de cadenas para extraer la ciudad a partir de la dirección

Es habitual tener un campo con direcciones en tablas de una BD. La dirección puede contener la calle, la ciudad… Esta lección te muestra cómo obtener solo la ciudad a partir de la dirección completa.

Se puede usar case para contar/sumar cosas que cumplan una determinada condición

Aunque la mejor forma de hacer consultas con funciones de agregación (cuenta, suma…) es usando group by, en ocasiones basta con usar una cláusula case dentro de la función de agregación. 

Cuidado con los comodines

Los comodines son útiles cuando queremos hacer comparaciones no exactas. Son sencillos de utilizar, pero con frecuencia se cometen algunos fallos que hay que evitar. Aquí hay algunos ejemplos de fallos habituales.

Cuidado con la preferencia de operadores lógicos

El operador and se evalúa antes que el or. Y si no tienes en cuenta este orden de preferencia puedes cometer errores al escribir condiciones complejas en el where de una consulta SQL.

Ordenar según el valor de expresiones mostradas en el select

Ordenar usando el valor de algún campo es sencillo. Basta con referirse al nombre del campo en la cláusula order by. Pero cuando el criterio de ordenación no es un campo, sino una expresión (con funciones u operadores) encontráis dificultades para referiros en el order by a esa expresión usada en el select. Aquí explicamos algunas formas de hacerlo.

¡Qué útil es la función coalesce!

Es frecuente ver cómo recurrís a usar una estructura case cuando tratáis de evitar que aparezca un valor null en un select y, en su lugar, queréis ver una leyenda alternativa como "valor no disponile". En estos casos es mejor recurrir a la función coalesce. Aquí tenéis un ejemplo:

Comprobación de no nulo

Los test de nulidad son muy sencillos de usar y escribir, aunque a veces se ven soluciones "imaginativas", que esconden fallos conceptuales graves, como en este caso.

Agrupar preferentemente incluyendo campos clave

Aunque no se pida explícitamente, siempre es más correcto, porque evita potenciales errores, incluir campos clave en el criterio de agrupación, además de los necesarios por estar incluidos en el select o having.

Pensar bien si hay que contar con distinct o sin él

Contar parece fácil. Pero hay que asegurarse de que no se cuentan valores repetidos, salvo que sea necesario. Este es un fallo frecuente. Lo estudiamos con unos sencillos ejemplos. 

No hace falta usar coalesce con count

En algunos ejemplos de agrupaciones, por ejemplo sobre el resultado de un outer join, hemos usado coalesce para evitar que aparezca un valor null como resultado de alguna función de agrupación sobre un grupo de valores que son todos nulos. 

Por ejemplo: la expresión sum(salario) devuelve null si todos los valores del campo salario en el grupo son null; pero coalesce(sum(salario), 0) devuelve 0.

Lo anterior no es necesario si la función de agrupación es count. La función count ya devuelve 0 si todos los valores contados son null

No usar group by en vez de select distinct

Cuando se trata de encontrar resultados sin repetidos, puedes estar tentado de usar group by en vez de select distinct. Aquí te explicamos por qué no debes hacerlo.