Dominio de Consultas Multitabla y Joins en Oracle Database

Producto Cartesiano en Bases de Datos

Cuando se extraen datos de múltiples tablas sin especificar una condición de unión válida, el motor de base de datos genera un producto catresiano. Esto significa que cada fila de la primera tabla se combina con cada fila de la segunda tabla, resultando en un conjunto de datos masivo y generalmente inútil para el análisis.

SELECT first_name, department_name 
FROM employees, departments;

El producto cartesiano ocurre típicamente cuando:

  • Se omite la cláusula de unión o la condición en el WHERE.
  • La condición de unión es inválida o evalúa siempre a verdadero.
  • Se cruzan todas las filas de todas las tablas involucradas sin restricciones.

Para prevenir este comportamiento, siempre se debe incluir una condición de filtrado adecuada en la cláusula WHERE o utilizar la sintaxis de JOIN explícita.

Sintaxis de Unión Tradicional en Oracle

En la sintaxis clásica, las tablas se listan en la cláusula FROM separadas por comas, y la lógica de unión se define posteriormente en la cláusula WHERE.

SELECT t1.column_a, t2.column_b
FROM table1 t1, table2 t2
WHERE t1.id_column = t2.id_column;

Cuando existen columnas con el mismo nombre en distintas tablas, es obligatorio utiilzar un prefijo (nombre de la tabla o alias) para evitar ambigüedades y errores de ejecución.

Equi-Join (Unión por Igualdad)

Es el tipo de unión más común, donde se relacionan filas basándose en la igualdad de valores en columnas específicas, generalmente claves primarias y foráneas.

SELECT emp.email, emp.phone_number, 
       dept.department_name, dept.manager_id
FROM employees emp, departments dept
WHERE emp.department_id = dept.department_id;

Múltiples Condiciones de Unión

Se pueden combinar condiciones de unión con filtros adicionales de negocio utilizando operadores lógicos como AND.

SELECT emp.employee_id, emp.last_name, 
       dept.department_name, loc.city
FROM employees emp, departments dept, locations loc
WHERE emp.department_id = dept.department_id 
  AND dept.location_id = loc.location_id
  AND emp.hire_date > TO_DATE('2015-01-01', 'YYYY-MM-DD');

Uso de Alias de Tabla

Los alias no solo hacen que el código SQL sea más legible, sino que también agilizan la escritura y mejoran el rendimiento del parseo al reducir la longitud del texto que el motor debe procesar.

Non-Equi-Join (Unión por Desigualdad)

Permite relacionar tablas cuando la condición no es una igualdad exacta, sino un rango o una desigualdad.

SELECT e.full_name, e.salary, j.grade_level
FROM staff e, salary_grades j
WHERE e.salary BETWEEN j.min_salary AND j.max_salary;

Inner Joins y Outer Joins con Sintaxis Propietaria

Un Inner Join (unión interna) solo devuelve las filas que tienen coincidencia en ambas tablas. Por otro lado, un Outer Join (unión externa) permite recuperar filas de una tabla incluso si no tienen correspondencia en la otra, rellenando los campos faltantes con valores NULL.

Operador de Outer Join en Oracle (+)

En la sintaxis tradicional de Oracle, el operador (+) se coloca en el lado de la tabla que puede tener valores nulos (el lado "opcional" de la relación).

-- Left Outer Join (Sintaxis Oracle)
SELECT p.product_name, c.category_name
FROM products p, categories c
WHERE p.category_id = c.category_id(+);

-- Right Outer Join (Sintaxis Oracle)
SELECT p.product_name, c.category_name
FROM products p, categories c
WHERE p.category_id(+) = c.category_id;

Self Join (Auto-Unión)

Se utiliza cuando una tabla necesita relacionarse consigo misma, típicamente en estructuras jerárquicas como empleados y sus gerentes o supervisores.

SELECT worker.first_name || ' reporta a ' || supervisor.first_name AS jerarquia
FROM hr_staff worker, hr_staff supervisor
WHERE worker.reports_to = supervisor.staff_id;

Estándar SQL:1999 para Uniones

El estándar ANSI SQL:1999 introdujo una sintaxis más clara y explícita para los joins, separando la lógica de unión de los filtros de negocio.

SELECT t1.col, t2.col
FROM table1 t1
[JOIN_TYPE] table2 t2
ON t1.key = t2.key;

Cross Join (Producto Cartesiano Explícito)

Ganera intencionalmente un producto cartesiano entre dos tablas mediante una cláusula específica.

SELECT region_name, country_name
FROM regions
CROSS JOIN countries;

Natural Join

Realiza una unión automática basada en todas las columnas que comparten el mismo nombre y tipo de dato en ambas tablas. Si los tipos de dato difieren, la consulta fallará.

SELECT department_id, department_name, street_address
FROM departments
NATURAL JOIN locations;

Cláusula USING

Similar al NATURAL JOIN, pero permite especificar explícitamente qué columnas con el mismo nombre se utilizarán para la unión. Las columnas listadas en USING no deben llevar prefijo de tabla en la cláusula SELECT.

SELECT employee_id, last_name, department_name
FROM employees
JOIN departments USING (department_id);

Cláusula ON

Es la forma más flexible y recomendada de definir uniones. Permite especificar condiciones de unión incluso cuando las columnas tienen nombres diferentes, y mejora drásticamente la legibilidad y el mantenimiento del código.

SELECT e.employee_id, e.job_id, j.job_title
FROM employees e 
JOIN jobs j
ON e.job_id = j.job_id;

Uniones Múltiples con ON

SELECT e.first_name, d.department_name, l.country_id
FROM employees e 
JOIN departments d ON e.department_id = d.department_id 
JOIN locations l ON d.location_id = l.location_id;

Outer Joins en SQL:1999

El estándar moderno define tres tipos de uniones externas, donde la palabra clave OUTER es opcional y puede omitirse para simplificar la sintaxis.

Left Outer Join

Retorna todas las filas de la tabla izquierda y las coincidencias de la tabla derecha. Si no hay coincidencia, los campos de la tabla derecha serán NULL.

SELECT c.customer_name, o.order_date
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id;

Right Outer Join

Retorna todas las filas de la tabla derecha y las coincidencias de la tabla izquierda.

SELECT c.customer_name, o.order_date
FROM customers c
RIGHT JOIN orders o ON c.customer_id = o.customer_id;

Full Outer Join

Retorna todas las filas de ambas tablas, emparejando donde sea posible y rellenando con NULL en ambos lados donde no haya coincidencia mutua.

SELECT e.employee_name, d.department_name
FROM staff_directory e
FULL OUTER JOIN corporate_departments d 
ON e.dept_code = d.dept_code;

Etiquetas: Oracle SQL Joins SQL:1999 Outer Join

Publicado el 7-3 18:40