Consultas Compuestas en MySQL: Técnicas de Unión Multitabla, Autoconexión y Subconsultas

Revisión de Consultas Básicas

Supongamos una tabla de empleados con la siguiente estructura:

mysql> SELECT * FROM empleados;
+-----------+---------+-----------+------+------------+---------+---------+---------+
| id_emp    | nombre  | puesto    | mgr  | fec_alta   | salario | comision| id_dep  |
+-----------+---------+-----------+------+------------+---------+---------+---------+
| 1001      | MARTINEZ| ANALISTA  | 1005 | 1980-12-17 |  800.00 |    NULL |      20 |
| 1002      | GARCIA  | VENDEDOR  | 1003 | 1981-02-20 | 1600.00 |  300.00 |      30 |
| ... (otros registros) ... |
+-----------+---------+-----------+------+------------+---------+---------+---------+

Para encontrar empleados con salario superior a 500 o puesto 'GERENTE', cuyo nombre comience con 'J':

SELECT * FROM empleados WHERE (salario > 500 OR puesto = 'GERENTE') AND nombre LIKE 'J%';

Ordenar resultados por número de departamento ascendente y salario descendente:

SELECT * FROM empleados ORDER BY id_dep ASC, salario DESC;

Calcular el salario anual (salario * 12 + comisión, usando 0 si comisión es nula):

SELECT nombre, salario * 12 + IFNULL(comision, 0) AS 'salario_anual' FROM empleados ORDER BY salario_anual DESC;

Identificar al empleado con el salario máximo usando una subconsulta:

SELECT nombre, puesto FROM empleados WHERE salario = (SELECT MAX(salario) FROM empleados);

Listar empleados con salario superior al promedio:

SELECT nombre, salario FROM empleados WHERE salario > (SELECT AVG(salario) FROM empleados);

Resumir estadísticas por departamento, como salario promedio y máximo:

SELECT id_dep, AVG(salario), MAX(salario) FROM empleados GROUP BY id_dep;

Filtrar departamentos con salario promedio inferior a 2000:

SELECT id_dep, AVG(salario) AS promedio FROM empleados GROUP BY id_dep HAVING promedio < 2000;

Contar empleados y promedio salarial por puesto:

SELECT puesto, COUNT(*), AVG(salario) FROM empleados GROUP BY puesto;

Consultas Multitabla

Para combinar datos de diferentes tablas, como empleados y departamentos, se utiliza una unión basada en una clave común.

Ejemplo: Mostrar nombre de empleado, salario y nombre de departamento:

SELECT e.nombre, e.salario, d.nombre_dep 
FROM empleados e, departamentos d 
WHERE e.id_dep = d.id_dep;

Filtrar por departamento específico (por ejemplo, departamento 10):

SELECT d.nombre_dep, e.nombre, e.salario 
FROM empleados e, departamentos d 
WHERE e.id_dep = d.id_dep AND d.id_dep = 10;

Incluir datos de salarios por rango usando la tabla de grados salariales:

SELECT e.nombre, e.salario, g.grado 
FROM empleados e, grados_salariales g 
WHERE e.salario BETWEEN g.sal_min AND g.sal_max;

Autoconexión

La autoconexión permite consultar una tabla relacionada consigo misma, por ejemplo, para encontrar el suprevisor directo de un empleado.

Para obtener el supervisor de 'FORD' (suponiendo que 'mgr' es el id del supervisor):

SELECT sup.nombre, sup.id_emp 
FROM empleados e, empleados sup 
WHERE e.nombre = 'FORD' AND e.mgr = sup.id_emp;

Subconsultas

Las subconsultas son consultas anidadas dentro de otra consulta SQL.

Subconsulta de una sola fila

Encontrar empleados que pertenecen al mismo departamento que 'MARTINEZ':

SELECT * FROM empleados 
WHERE id_dep = (SELECT id_dep FROM empleados WHERE nombre = 'MARTINEZ');

Subconsulta de múltiples filas

Usar 'IN' para comparar con un conjunto de valores. Ejemplo: empleados con puestos iguales a los del departamento 10, excluyendo el departamento 10:

SELECT nombre, puesto, salario, id_dep 
FROM empleados 
WHERE puesto IN (SELECT puesto FROM empleados WHERE id_dep = 10) AND id_dep <> 10;

Usar 'ALL' para comparar con todos los valores de una subconsulta. Ejemplo: empleados con salario mayor que todos los del departamento 30:

SELECT nombre, salario, id_dep 
FROM empleados 
WHERE salario > ALL (SELECT salario FROM empleados WHERE id_dep = 30);

Usar 'ANY' para comparar con al menos un valor. Ejemplo: empleados con salario mayor que algún empleado del departamento 30, excluyendo el departamento 30:

SELECT nombre, salario, id_dep 
FROM empleados 
WHERE salario > ANY (SELECT salario FROM empleados WHERE id_dep = 30) AND id_dep <> 30;

Subconsulta multicomparada

Buscar empleados con departamento y puesto idénticos a 'MARTINEZ', excluyendo a 'MARTINEZ':

SELECT * FROM empleados 
WHERE (id_dep, puesto) = (SELECT id_dep, puesto FROM empleados WHERE nombre = 'MARTINEZ') 
AND nombre <> 'MARTINEZ';

Subconsultas en la cláusula FROM

Tratar una subconsulta como una tabla temporal. Ejemplo: mostrar empleados cuyo salario supere el promedio de su departamento, incluyendo el promedio:

SELECT t1.nombre, t1.id_dep, t1.salario, t2.promedio 
FROM empleados t1, 
(SELECT id_dep, AVG(salario) AS promedio FROM empleados GROUP BY id_dep) t2 
WHERE t1.id_dep = t2.id_dep AND t1.salario > t2.promedio;

Para encontrar el empleado con mayor salario por departamento:

SELECT t1.nombre, t1.salario, t1.id_dep, t2.max_sal 
FROM empleados t1, 
(SELECT id_dep, MAX(salario) AS max_sal FROM empleados GROUP BY id_dep) t2 
WHERE t1.id_dep = t2.id_dep AND t1.salario = t2.max_sal;

Combinar información de departamentos con el número de empleados:

SELECT d.id_dep, d.nombre_dep, d.ubicacion, t.cantidad 
FROM departamentos d, 
(SELECT id_dep, COUNT(*) AS cantidad FROM empleados GROUP BY id_dep) t 
WHERE d.id_dep = t.id_dep;

Consultas de combinación con UNION y UNION ALL

UNION combina resultados de múltiples consultas eliminando duplicados. Ejemplo: empleados con salario mayor a 2500 o puesto 'GERENTE':

SELECT * FROM empleados WHERE salario > 2500 
UNION 
SELECT * FROM empleados WHERE puesto = 'GERENTE';

UNION ALL combina resultados sin eliminar duplicados. Ejemplo similar:

SELECT * FROM empleados WHERE salario > 2500 
UNION ALL 
SELECT * FROM empleados WHERE puesto = 'GERENTE';

La esencia de resolver consultas multitabla es reducirlas a problemas de una sola tabla mediante técnicas como uniones y subconsultas.

Etiquetas: MySQL SQL consultas multitabla autoconexión Subconsultas

Publicado el 7-3 09:00