SQL para Principiantes (Parte 3): La Cláusula WHERE

  • Preparar
  • Introducción
  • Condiciones de igualdad y desigualdad
  • Condiciones IN y NOT IN
  • Condiciones EXISTS y NOT EXISTS
  • Condiciones BETWEEN y NOT BETWEEN 
  • Condiciones LIKE y NOT LIKE 
  • OR condición
  • Conclusión

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

La cláusula WHERE se utiliza para filtrar el conjunto de resultados. Si las condiciones de filtro en la cláusula WHERE se evalúan como FALSE para una fila específica, esa fila no se devuelve en el conjunto de resultados final. Se pueden agrupar varias condiciones de filtro mediante las condiciones Y y O.

Cuando se utiliza la sintaxis de combinación no ANSI, la cláusula WHERE contiene condiciones de combinación y condiciones de filtro.

SELECT e.employee_name, e.salary, d.department_id, d.department_name
FROM   employees e, departments d
WHERE  e.department_id = d.department_id  -- Join Condition
AND    d.department_id = 20               -- Filter
AND    e.salary >= 2000                   -- Filter
ORDER BY e.employee_name;

EMPLOYEE_N     SALARY DEPARTMENT_ID DEPARTMENT_NAM
---------- ---------- ------------- --------------
FORD             3000            20 RESEARCH
JONES            2975            20 RESEARCH
SCOTT            3000            20 RESEARCH

3 rows selected.

SQL>

Cuando se usa la sintaxis de combinación ANSI, la cláusula WHERE solo contiene condiciones de filtro.

SELECT e.employee_name, e.salary, d.department_id, d.department_name
FROM   employees e
       JOIN departments d ON e.department_id = d.department_id
WHERE  d.department_id = 20               -- Filter
AND    e.salary >= 2000                   -- Filter
ORDER BY e.employee_name;

EMPLOYEE_N     SALARY DEPARTMENT_ID DEPARTMENT_NAM
---------- ---------- ------------- --------------
FORD             3000            20 RESEARCH
JONES            2975            20 RESEARCH
SCOTT            3000            20 RESEARCH

3 rows selected.

SQL>

En el resto de este artículo, veremos los tipos de condiciones que probablemente verá en la cláusula WHERE. Recuerde, esta no es una lista exhaustiva, solo algunas de las cosas más comunes. Para simplificar las cosas, los siguientes ejemplos usarán la sintaxis de combinación ANSI, por lo que la cláusula WHERE solo contiene condiciones de filtro.

Condiciones de igualdad y desigualdad

Las condiciones de filtro pueden utilizar pruebas básicas de igualdad y desigualdad.

=: Igual.
<> o! =: No es igual.
>: Mayor que.
<: Menos de. > =: Mayor o igual que.
<=: Menor o igual.

SELECT e.employee_name, e.department_id, e.salary
FROM   employees e
WHERE  e.department_id = 20
AND    e.salary >= 2000
ORDER BY e.employee_name;

EMPLOYEE_N DEPARTMENT_ID     SALARY
---------- ------------- ----------
FORD                  20       3000
JONES                 20       2975
SCOTT                 20       3000

3 rows selected.

SQL>

Condiciones IN y NOT IN

La condición IN se evalúa como TRUE para los valores de columna en la lista especificada.

SELECT e.department_id, e.employee_id, e.employee_name
FROM   employees e
WHERE  e.department_id IN (10, 20)
ORDER BY e.department_id, e.employee_id;

DEPARTMENT_ID EMPLOYEE_ID EMPLOYEE_N
------------- ----------- ----------
           10        7782 CLARK
           10        7839 KING
           10        7934 MILLER
           20        7369 SMITH
           20        7566 JONES
           20        7788 SCOTT
           20        7876 ADAMS
           20        7902 FORD

8 rows selected.

SQL>

La condición NOT IN se evalúa como TRUE para los valores de columna que no están en la lista especificada.

SELECT e.department_id, e.employee_id, e.employee_name
FROM   employees e
WHERE  e.department_id NOT IN (10, 20)
ORDER BY e.department_id, e.employee_id;

DEPARTMENT_ID EMPLOYEE_ID EMPLOYEE_N
------------- ----------- ----------
           30        7499 ALLEN
           30        7521 WARD
           30        7654 MARTIN
           30        7698 BLAKE
           30        7844 TURNER
           30        7900 JAMES

6 rows selected.

SQL>

Las condiciones IN y NOT IN se pueden evaluar con los valores devueltos por una subconsulta.

SELECT e.department_id, e.employee_id, e.employee_name
FROM   employees e
WHERE  e.department_id IN (SELECT d.department_id
                           FROM   departments d
                           WHERE  d.department_id < 30) ORDER BY e.department_id, e.employee_id; DEPARTMENT_ID EMPLOYEE_ID EMPLOYEE_N ------------- ----------- ---------- 10 7782 CLARK 10 7839 KING 10 7934 MILLER 20 7369 SMITH 20 7566 JONES 20 7788 SCOTT 20 7876 ADAMS 20 7902 FORD 8 rows selected. SQL>

Condiciones EXISTS y NOT EXISTS

La condición EXISTS se evalúa como TRUE si la subconsulta devuelve una o más filas.

SELECT d.department_id, d.department_name
FROM   departments d
WHERE  EXISTS (SELECT 1
               FROM   employees e
               WHERE  d.department_id = e.department_id)
ORDER BY d.department_id;

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

3 rows selected.

SQL>

La condición NOT EXISTS se evalúa como TRUE si la subconsulta devuelve cero filas.

SELECT d.department_id, d.department_name
FROM   departments d
WHERE  NOT EXISTS (SELECT 1
                   FROM   employees e
                   WHERE  d.department_id = e.department_id)
ORDER BY d.department_id;

DEPARTMENT_ID DEPARTMENT_NAM
------------- --------------
           40 OPERATIONS

1 row selected.

SQL>

BETWEEN y NOT BETWEEN Condiciones

La condición BETWEEN se evalúa como TRUE para los valores de columna dentro del rango especificado, incluidos los límites.

SELECT d.department_id, d.department_name
FROM   departments d
WHERE  department_id BETWEEN 20 AND 40
ORDER BY d.department_id;

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

3 rows selected.

SQL>

La condición NOT BETWEEN se evalúa como TRUE para los valores de columna que no se encuentran dentro del rango especificado, incluidos los límites.

SELECT d.department_id, d.department_name
FROM   departments d
WHERE  department_id NOT BETWEEN 20 AND 40
ORDER BY d.department_id;

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

1 row selected.

SQL>

Condiciones LIKE y NOT LIKE

La condición LIKE se evalúa como TRUE si hay una coincidencia de patrón. El ‘%’ es un comodín de longitud variable. El ‘_’ es un comodín de un solo carácter.

SELECT d.department_id, d.department_name
FROM   departments d
WHERE  department_name LIKE '%O%'
ORDER BY d.department_id;

DEPARTMENT_ID DEPARTMENT_NAM
------------- --------------
           10 ACCOUNTING
           40 OPERATIONS

2 rows selected.

SQL>

La condición NOT LIKE se evalúa como TRUE si no hay coincidencia de patrón.

SELECT d.department_id, d.department_name
FROM   departments d
WHERE  department_name NOT LIKE '%O%'
ORDER BY d.department_id;

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

2 rows selected.

SQL>

Condición OR

Tenga cuidado al vincular condiciones en la cláusula WHERE utilizando la condición OR. Es fácil estropear tu lógica. En el siguiente ejemplo, creo que he solicitado gerentes y empleados del departamento 20.

SELECT e.employee_id, e.employee_name, e.department_id, e.salary, e.job
FROM   employees e
WHERE  e.department_id = 20
AND    e.job = 'MANAGER'
OR     e.job = 'CLERK'
ORDER BY e.employee_id;

EMPLOYEE_ID EMPLOYEE_N DEPARTMENT_ID     SALARY JOB
----------- ---------- ------------- ---------- ---------
       7369 SMITH                 20        800 CLERK
       7566 JONES                 20       2975 MANAGER
       7876 ADAMS                 20       1100 CLERK
       7900 JAMES                 30        950 CLERK
       7934 MILLER                10       1300 CLERK

5 rows selected.

SQL>

Podemos ver en el resultado que también hemos devuelto empleados de los departamentos 30 y 10. Esto se debe a que la condición OR ha cancelado la condición del departamento si el empleado es un empleado.

Deberíamos haber utilizado paréntesis para asegurarnos de que estábamos haciendo la pregunta correcta.

SELECT e.employee_id, e.employee_name, e.department_id, e.salary, e.job
FROM   employees e
WHERE  e.department_id = 20
AND    (e.job = 'MANAGER' OR e.job = 'CLERK')
ORDER BY e.employee_id;

EMPLOYEE_ID EMPLOYEE_N DEPARTMENT_ID     SALARY JOB
----------- ---------- ------------- ---------- ---------
       7369 SMITH                 20        800 CLERK
       7566 JONES                 20       2975 MANAGER
       7876 ADAMS                 20       1100 CLERK

3 rows selected.

SQL>

Conclusión

Acabamos de arañar la superficie aquí. Hay muchas funciones, condiciones y operadores con los que entrará en contacto en el transcurso de su trabajo con SQL, pero todas son adiciones a esta base. Comprenda los conceptos básicos y las otras cosas irán encajando con el tiempo.
Los principiantes a menudo encuentran combinaciones bastante confusas y tienden a gravitar hacia las condiciones IN y EXISTS para filtrar datos, incluso en los casos en los que sería más eficiente unirse a la tabla específica y usar un filtro simple en su contra. En los primeros días probablemente se concentrará en tratar de obtener los resultados correctos, pero para su desarrollo a largo plazo, debe probar tantos métodos diferentes para obtener los mismos resultados como sea posible y comparar el rendimiento. Siempre es bueno conocer soluciones alternativas y, con el tiempo, conocerá qué condiciones funcionan mejor en qué situaciones.
También debe tener en cuenta que lo que escribe no siempre es lo que ejecuta Oracle. En algunos casos, el optimizador transformará (reescribirá) su declaración. Por ejemplo, una condición IN que usa una lista puede expandirse a un grupo de condiciones de igualdad vinculadas con condiciones OR. No se obsesione con esto en las primeras etapas, pero a medida que se desarrolle, deberá comenzar a considerar esto al elegir las condiciones de filtro que usará.

Deja un comentario

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