SQL para Principiantes (Parte 6): Establecer Operadores

  • Preparar
  • Introducción
  • UNION
  • UNION ALL
  • INTERSECT
  • MINUS
  • ORDER BY
  • Data Types

Preparar

Puede realizar todas estas consultas en línea de forma gratuita utilizando SQL Fiddle.

Los ejemplos de este artículo requieren que estén presentes las siguientes tablas.

--DROP TABLE employees PURGE;
--DROP TABLE departments PURGE;

CREATE TABLE departments (
  department_id   NUMBER(2) CONSTRAINT departments_pk PRIMARY KEY,
  department_name VARCHAR2(14),
  location        VARCHAR2(13)
);
INSERT INTO departments VALUES (10,'ACCOUNTING','NEW YORK');
INSERT INTO departments VALUES (20,'RESEARCH','DALLAS');
INSERT INTO departments VALUES (30,'SALES','CHICAGO');
INSERT INTO departments VALUES (40,'OPERATIONS','BOSTON');
COMMIT;

CREATE TABLE employees (
  employee_id   NUMBER(4) CONSTRAINT employees_pk PRIMARY KEY,
  employee_name VARCHAR2(10),
  job           VARCHAR2(9),
  manager_id    NUMBER(4),
  hiredate      DATE,
  salary        NUMBER(7,2),
  commission    NUMBER(7,2),
  department_id NUMBER(2) CONSTRAINT emp_department_id_fk REFERENCES departments(department_id)
);
INSERT INTO employees VALUES (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
INSERT INTO employees VALUES (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
INSERT INTO employees VALUES (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
INSERT INTO employees VALUES (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
INSERT INTO employees VALUES (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
INSERT INTO employees VALUES (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
INSERT INTO employees VALUES (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
INSERT INTO employees VALUES (7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87','dd-mm-rr')-85,3000,NULL,20);
INSERT INTO employees VALUES (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
INSERT INTO employees VALUES (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
INSERT INTO employees VALUES (7876,'ADAMS','CLERK',7788,to_date('13-JUL-87', 'dd-mm-rr')-51,1100,NULL,20);
INSERT INTO employees VALUES (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
INSERT INTO employees VALUES (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
INSERT INTO employees VALUES (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
COMMIT;

Estas tablas son una variante de las tablas EMP y DEPT del esquema SCOTT. Verá muchos ejemplos de Oracle en Internet utilizando las tablas del esquema de SCOTT. Puede encontrar las definiciones de la tabla original en el script «$ORACLE_HOME/rdbms/admin/utlsampl.sql».
Introducción
Los operadores de conjunto le permiten combinar los resultados de varias consultas independientes en un único conjunto de resultados.
Las siguientes dos consultas se utilizarán para la mayoría de los ejemplos de este artículo. El primero devuelve los departamentos 10, 20 y 30. El segundo devuelve los departamentos 20, 30 y 40. Como puede ver, los departamentos 20 y 30 son comunes a ambos conjuntos de resultados.

-- Departmentos 10, 20 y 30.
SELECT department_id, department_name
FROM   departments
WHERE  department_id <= 30; DEPARTMENT_ID DEPARTMENT_NAM ------------- -------------- 10 ACCOUNTING 20 RESEARCH 30 SALES 3 rows selected. SQL>
--Departmentos 20, 30 y 40.
SELECT department_id, department_name
FROM   departments
WHERE  department_id >= 20;

DEPARTMENT_ID DEPARTMENT_NAM
------------- --------------
           20 RESEARCH
           30 SALES
           40 OPERATIONS

3 rows selected.

SQL>

Verá, estos no son ejemplos del mundo real, pero sirven para demostrar cómo funciona cada uno de los operadores de conjuntos.

UNIÓN

El operador de conjunto UNION devuelve todas las filas distintas seleccionadas por cualquiera de las consultas. Eso significa que se eliminarán las filas duplicadas.

En el siguiente ejemplo, observe que solo hay una fila para cada departamento 20 y 30, en lugar de dos para cada uno.

SELECT department_id, department_name
FROM   departments
WHERE  department_id <= 30 UNION SELECT department_id, department_name FROM departments WHERE department_id >= 20
ORDER BY 1;

DEPARTMENT_ID DEPARTMENT_NAM
------------- --------------
           10 ACCOUNTING
           20 RESEARCH
           30 SALES
           40 OPERATIONS

4 rows selected.

SQL>

La eliminación de duplicados requiere un procesamiento adicional, por lo que debería considerar usar UNION ALL si es posible.

UNIÓN ALL

El operador de conjunto UNION ALL devuelve todas las filas seleccionadas por cualquiera de las consultas. Eso significa que cualquier duplicado permanecerá en el conjunto de resultados final.

En el siguiente ejemplo, observe que hay dos filas para cada departamento 20 y 30.

SELECT department_id, department_name
FROM   departments
WHERE  department_id <= 30 UNION ALL SELECT department_id, department_name FROM departments WHERE department_id >= 20
ORDER BY 1;

DEPARTMENT_ID DEPARTMENT_NAM
------------- --------------
           10 ACCOUNTING
           20 RESEARCH
           20 RESEARCH
           30 SALES
           30 SALES
           40 OPERATIONS

6 rows selected.

SQL>

INTERSECT

El operador de conjunto INTERSECT devuelve todas las filas distintas seleccionadas por ambas consultas. Eso significa que solo las filas comunes a ambas consultas estarán presentes en el conjunto de resultados final.
En el siguiente ejemplo, observe que hay una fila para cada departamento 20 y 30, ya que ambos aparecen en los conjuntos de resultados para sus consultas respectivas.

SELECT department_id, department_name
FROM   departments
WHERE  department_id <= 30 INTERSECT SELECT department_id, department_name FROM departments WHERE department_id >= 20
ORDER BY 1;

DEPARTMENT_ID DEPARTMENT_NAM
------------- --------------
           20 RESEARCH
           30 SALES

2 rows selected.

SQL>

MINUS

El operador de conjunto MINUS devuelve todas las filas distintas seleccionadas por la primera consulta, pero no la segunda. Esto es funcionalmente equivalente al operador de conjunto ANSI EXCEPT DISTINCT.
En el siguiente ejemplo, la primera consulta devolvería los departamentos 10, 20, 30, pero los departamentos 20 y 30 se eliminan porque son devueltos por la segunda consulta. Esto deja una sola fila para el departamento 10.

SELECT department_id, department_name
FROM   departments
WHERE  department_id <= 30 MINUS SELECT department_id, department_name FROM departments WHERE department_id >= 20
ORDER BY 1;

DEPARTMENT_ID DEPARTMENT_NAM
------------- --------------
           10 ACCOUNTING

1 row selected.

SQL>

ORDER BY

La cláusula ORDER BY se aplica a todas las filas devueltas en el conjunto de resultados final. Se puede hacer referencia a las columnas de la cláusula ORDER BY mediante nombres de columna o alias de columna presentes en la primera consulta de la declaración, ya que estos se trasladan al conjunto de resultados final. Por lo general, verá que las personas usan la posición de la columna, ya que es menos confuso cuando los datos se obtienen de diferentes ubicaciones para cada bloque de consulta.

-- Nombre Columnas.
SELECT employee_id, employee_name
FROM   employees
WHERE  department_id = 10
UNION ALL
SELECT department_id, department_name
FROM   departments
WHERE  department_id >= 20
ORDER BY employee_id;

EMPLOYEE_ID EMPLOYEE_NAME
----------- --------------
         20 RESEARCH
         30 SALES
         40 OPERATIONS
       7782 CLARK
       7839 KING
       7934 MILLER

6 rows selected.

SQL>
-- Alias Columnas.
SELECT employee_id AS emp_id, employee_name
FROM   employees
WHERE  department_id = 10
UNION ALL
SELECT department_id, department_name
FROM   departments
WHERE  department_id >= 20
ORDER BY emp_id;

    EMP_ID EMPLOYEE_NAME
---------- --------------
        20 RESEARCH
        30 SALES
        40 OPERATIONS
      7782 CLARK
      7839 KING
      7934 MILLER

6 rows selected.

SQL>
-- Column position
SELECT employee_id, employee_name
FROM   employees
WHERE  department_id = 10
UNION ALL
SELECT department_id, department_name
FROM   departments
WHERE  department_id >= 20
ORDER BY 1;

EMPLOYEE_ID EMPLOYEE_NAME
----------- --------------
         20 RESEARCH
         30 SALES
         40 OPERATIONS
       7782 CLARK
       7839 KING
       7934 MILLER

6 rows selected.

SQL>

No se permite hacer referencia a nombres de columna o alias de columna en consultas posteriores.

-- Nombre de columna iconrrecta
SELECT employee_id, employee_name
FROM   employees
WHERE  department_id = 10
UNION ALL
SELECT department_id, department_name
FROM   departments
WHERE  department_id >= 20
ORDER BY department_id;

ORDER BY department_id
         *
ERROR at line 8:
ORA-00904: "DEPARTMENT_ID": invalid identifier

SQL>
-- columna o alias incorrecto
SELECT employee_id, employee_name
FROM   employees
WHERE  department_id = 10
UNION ALL
SELECT department_id AS dept_id, department_name
FROM   departments
WHERE  department_id >= 20
ORDER BY dept_id;

ORDER BY dept_id
         *
ERROR at line 8:
ORA-00904: "DEPT_ID": invalid identifier

SQL>

Data Types

Los tipos de datos deben coincidir para la misma posición de columna en cada consulta. Algunas conversiones implícitas serán posibles entre algunos tipos de datos, por ejemplo CHAR/VARCHAR2, o conversión entre algunos tipos numéricos.
En el siguiente ejemplo, convertimos la columna EMPLOYEE_ID a VARCHAR2 usando la función TO_CHAR, que rompe la declaración.

SELECT TO_CHAR(employee_id) AS employee_id, employee_name
FROM   employees
WHERE  department_id = 10
UNION ALL
SELECT department_id, department_name
FROM   departments
WHERE  department_id >= 20
ORDER BY 1;
SELECT TO_CHAR(employee_id) AS employee_id, employee_name
*
ERROR at line 1:
ORA-01790: expression must have same datatype as corresponding expression

SQL>

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *