SELF JOIN EN MYSQL: GUÍA COMPLETA Y PRÁCTICA
Un Self JOIN consiste en hacer referencia a la misma tabla más de una vez en una consulta, asignándole alias diferentes para poder diferenciarlas. Sintaxis básica:SELECT
t1.columna1,
t2.columna2
FROM tabla AS t1
JOIN tabla AS t2 ON t1.columna_relacion = t2.columna_relacion
WHERE ...;
Ejemplo clásico
Buscar empleados y sus jefes: Se tiene una tabla empleados donde cada empleado tiene un "jefe_id" que referencia al id de otro empleado de la misma tabla:CREATE TABLE empleados (
id INT PRIMARY KEY,
nombre VARCHAR(100),
jefe_id INT,
salario DECIMAL(10,2)
);
INSERT INTO empleados VALUES
(1, 'Carlos López', NULL, 8000),
(2, 'María García', 1, 6500),
(3, 'Juan Pérez', 1, 6200),
(4, 'Ana Martínez', 2, 5500),
(5, 'Luis Rodríguez', 2, 5800);
SELECT
e.nombre AS empleado,
j.nombre AS jefe,
e.salario AS salario_empleado
FROM empleados e
LEFT JOIN empleados j ON e.jefe_id = j.id
ORDER BY e.nombre;
Resultado esperado
Se usa "LEFT JOIN" para incluir al empleado que no tiene jefe porque es el director general.Otros casos de uso comunes
Encontrar duplicados o registros similares
-- Encontrar productos con el mismo precio
SELECT
p1.nombre AS producto1,
p2.nombre AS producto2,
p1.precio
FROM productos p1
JOIN productos p2 ON p1.precio = p2.precio
AND p1.id < p2.id; -- Evita duplicados (p1 con p2 y p2 con p1)
Comparación de fechas o periodos
-- Comparar ventas del mes actual con el mes anterior
SELECT
v1.mes,
v1.total AS total_actual,
v2.total AS total_mes_anterior
FROM ventas_mensuales v1
LEFT JOIN ventas_mensuales v2
ON v1.mes = DATE_ADD(v2.mes, INTERVAL 1 MONTH);
Árbol jerárquico (categorías, comentarios, etc.)
-- Categorías padre-hijo
SELECT
c.nombre AS categoria,
p.nombre AS categoria_padre
FROM categorias c
LEFT JOIN categorias p ON c.padre_id = p.id;
Ejemplo con CTE recursivo (MySQL 8.0+)
WITH RECURSIVE jerarquia AS (
SELECT id, nombre, jefe_id, 0 AS nivel
FROM empleados
WHERE jefe_id IS NULL
UNION ALL
SELECT e.id, e.nombre, e.jefe_id, j.nivel + 1
FROM empleados e
JOIN jerarquia j ON e.jefe_id = j.id
)
SELECT * FROM jerarquia;
Consideraciones de Rendimiento
- Los índices son fundamentales: Asegurarse de tener índices en las columnas donde se usan en la condición "ON".
- Evita Cartesian products: Siempre incluye una condición en el "ON", salvo que realmente se necesite un "CROSS JOIN".
- El uso de "Alias" es obligatorios: Sin "Alias" la consulta fallará o será confusa.
- "Self JOIN" y "GROUP BY": Es muy potente para análisis, pero puede ser costoso en tablas grandes.