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.

Supongamos que tenemos dos tablas, una con información de empleados de una empresa y otra con los familiares de estos empleados (te llamo la atención sobre el hecho de que hay dos empleados que se llaman igual, aunque tienen distinto identificador):

Empleado
+----+------------+
| id | nombre     |
+----+------------+
|  1 | Pepe Pérez |
|  2 | Ana Abad   |
|  3 | Pepe Pérez |
+----+------------+
3 rows in set (0.00 sec)
Familiar
+------------+---------------+------------+
| idEmpleado | nombre        | parentesco |
+------------+---------------+------------+
|          1 | Eduardo Pérez | Hijo       |
|          1 | Ana Pérez     | Hija       |
|          1 | Ana Llopis    | Esposa     |
|          2 | Carlos Cruz   | Esposo     |
|          3 | Nuria Pérez   | Hija       |
|          3 | Bea Bez       | Esposa     |
+------------+---------------+------------+
6 rows in set (0.00 sec)

Queremos contar el número de familiares de cada empleado, incluyendo en el listado el nombre del empleado y sus familiares. Podríamos intentar la siguiente consulta, con un join de ambas tablas y una agrupación por nombre de empleado, ya que este es el campo que nos piden en el listado:

MAL
select e.nombre, count(*) familiares
from Empleado e join Familiar f on e.id = f.idEmpleado
group by e.nombre;

El resultado que obtenemos es el siguiente, que a todas luces es erróneo, pues no reconoce la existencia de los dos empleados que se llaman igual, y mezcla los familiares de ambos en un mismo grupo:

+------------+------------+
| nombre     | familiares |
+------------+------------+
| Pepe Pérez |          5 |
| Ana Abad   |          1 |
+------------+------------+
2 rows in set (0.00 sec)

Debería haber dos filas para los dos empleado llamados 'Pepe Pérez', uno con tres familiares y otra con dos.

Tal error se evita muy fácilmente incluyendo el campo e.id en el group by, aunque este campo no se use en el select (nota como el group by sigue manteniendo el campo nombre, porque este aparece en el select):

BIEN
select e.nombre, count(*) familiares
from Empleado e join Familiar f on e.id = f.idEmpleado
group by e.id, e.nombre;

Así el resultado será el correcto:

+------------+------------+
| nombre     | familiares |
+------------+------------+
| Pepe Pérez |          3 |
| Ana Abad   |          1 |
| Pepe Pérez |          2 |
+------------+------------+
3 rows in set (0.00 sec)

No hay comentarios:

Publicar un comentario