SQL em Oracle > DML > Subconsultas > Subconsulta que devolve várias linhas - operadores do SQL
Subconsulta que devolve várias linhas - operadores do SQL tl_logo2.jpg

Os exemplos de subconsulta que vimos até agora devolvem apenas uma linha. Mas uma subconsulta pode devolver várias linhas, o que obriga a consulta externa a ter cuidados especiais e a recorrer aos operadores do SQL:


IN

Quando a subconsulta devolve várias linhas o operador IN pode ser usado para validar se uma linha da consulta externa está presente no conjunto criado pela subconsulta. Devolve TRUE se o(s) valor(es) usado(s) na consulta externa está(ão) incluído(s) no conjunto devolvido pela consulta interna. Este operador pode ser negado com NOT.

Suponha que pretende determinar os empregados que ganham o salário mais baixo em cada função, usando a tabela EMPLOYEES. A consulta abaixo tenta responder a esta pergunta, mas sem sucesso.

sentidoproibido.gif

select first_name,salary,job_id
from employees
where salary in (select min(salary) 
                 from employees
                 group by job_id)
order by job_id, salary;
FIRST_NAME               SALARY JOB_ID   
-------------------- ---------- ----------
Randall                    2500 SH_CLERK   
Steven                    24000 AD_PRES    
Neena                     17000 AD_VP      
Lex                       17000 AD_VP      
Bruce                      6000 IT_PROG    
Diana                      4200 IT_PROG
Nancy                     12008 FI_MGR     
Luis                       6900 FI_ACCOUNT 
Den                       11000 PU_MAN     
Karen                      2500 PU_CLERK   
Shanta                     6500 ST_MAN     
Kevin                      5800 ST_MAN     
James                      2500 ST_CLERK   
TJ                         2100 ST_CLERK   
Joshua                     2500 ST_CLERK   
Peter                      2500 ST_CLERK   
Gerald                    11000 SA_MAN     
Eleni                     10500 SA_MAN     
Peter                     10000 SA_REP     
Janette                   10000 SA_REP     
Clara                     10500 SA_REP     
Harrison                  10000 SA_REP     
Sundita                    6100 SA_REP     
Ellen                     11000 SA_REP     
Martha                     2500 SH_CLERK   
Nandita                    4200 SH_CLERK   
Jennifer                   4400 AD_ASST    
Michael                   13000 MK_MAN     
Pat                        6000 MK_REP     
Susan                      6500 HR_REP     
Hermann                   10000 PR_REP     
Shelley                   12008 AC_MGR     
William                    8300 AC_ACCOUNT 

 33 rows selected

A forma de associar a função ao salário mínimo é devolver e comparar o par de valores, como no exemplo abaixo:

select first_name,salary,job_id
from employees
where (job_id,salary) in (select job_id,min(salary) 
                          from employees
                          group by job_id)
order by job_id, salary;
FIRST_NAME               SALARY JOB_ID   
-------------------- ---------- ----------
William                    8300 AC_ACCOUNT 
Shelley                   12008 AC_MGR     
Jennifer                   4400 AD_ASST    
Steven                    24000 AD_PRES    
Lex                       17000 AD_VP      
Neena                     17000 AD_VP      
Luis                       6900 FI_ACCOUNT 
Nancy                     12008 FI_MGR     
Susan                      6500 HR_REP     
Diana                      4200 IT_PROG    
Michael                   13000 MK_MAN     
Pat                        6000 MK_REP     
Hermann                   10000 PR_REP     
Karen                      2500 PU_CLERK   
Den                       11000 PU_MAN     
Eleni                     10500 SA_MAN     
Sundita                    6100 SA_REP
Randall                    2500 SH_CLERK   
Martha                     2500 SH_CLERK   
TJ                         2100 ST_CLERK   
Kevin                      5800 ST_MAN     

 21 rows selected 

bthome.gifTopo


ANY (SOME)

O operador ANY (e o seu sinónimo SOME) permite a uma consulta externa fazer comparações usando < ou > com os elementos de um conjunto devolvido pela subconsulta. Este operador devolve TRUE se uma das linhas do conjunto satisfaz a condição, ou seja, devolve FALSE se nenhuma satisfaz a condição. Este operador pode ser negado com NOT.

A consulta abaixo devolve os empregados que ganham mais que algum empregado do departamento 30. Isto é o mesmo que afirmar que procuramos os que ganham mais que o salário mínimo do departamento 30.

select ename, sal, job, deptno
from emp
where sal > ANY (select distinct sal
                 from emp
                 where deptno=30);
ENAME      SAL                    JOB       DEPTNO                 
---------- ---------------------- --------- ---------------------- 
KING       5000                   PRESIDENT 10                     
FORD       3000                   ANALYST   20                     
SCOTT      3000                   ANALYST   20                     
JONES      2975                   MANAGER   20                     
BLAKE      2850                   MANAGER   30                     
CLARK      2450                   MANAGER   10                     
ALLEN      1600                   SALESMAN  30                     
TURNER     1500                   SALESMAN  30                     
MILLER     1300                   CLERK     10                     
WARD       1250                   SALESMAN  30                     
MARTIN     1250                   SALESMAN  30                     
ADAMS      1100                   CLERK     20                     

12 rows selected

bthome.gifTopo


ALL

O operador ALL permite a uma consulta externa fazer comparações usando < ou > com os elementos de um conjunto devolvido pela subconsulta. Este operador devolve TRUE se todas as linhas do conjunto satisfazem a condição, ou seja, devolve FALSE se alguma linha não a satisfaz. Este operador pode ser negado com NOT.

A consulta abaixo devolve os empregados que ganham mais que todos os empregados do departamento 30. Isto é o mesmo que afirmar que procuramos os que ganham mais que o salário máximo do departamento 30.

select ename, sal, job, deptno
from emp
where sal > ALL (select distinct sal
                 from emp
                 where deptno=30);
ENAME      SAL                    JOB       DEPTNO                 
---------- ---------------------- --------- ---------------------- 
JONES      2975                   MANAGER   20                     
SCOTT      3000                   ANALYST   20                     
KING       5000                   PRESIDENT 10                     
FORD       3000                   ANALYST   20                     

4 rows selected

bthome.gifTopo


EXISTS

O operador EXISTS permite à consulta externa verificar se a consulta interna devolveu alguma linha. Não se preocupa com o valor das linhas, mas sim com a cardinalidade do conjunto. Devolve TRUE se a cardinalidade for superior a 0 (zero) e FALSE caso seja igual a 0 (zero). Este operador pode ser negado com NOT.

O exemplo abaixo procura os empregados que tenham pelo menos um subordinado:

select m.empno,m.ename,m.job,m.deptno
from emp m
where exists (select e.empno
              from emp e
              where e.mgr=m.empno)
EMPNO                  ENAME      JOB       DEPTNO                 
---------------------- ---------- --------- ---------------------- 
7902                   FORD       ANALYST   20                     
7698                   BLAKE      MANAGER   30                     
7839                   KING       PRESIDENT 10                     
7566                   JONES      MANAGER   20                     
7788                   SCOTT      ANALYST   20                     
7782                   CLARK      MANAGER   10                     

6 rows selected

O exemplo abaixo procura todos os departamentos que não possuem empregados:

select d.deptno, d.dname
from dept d
where not exists (select deptno
                  from emp e
                  where e.deptno=d.deptno);
                  
DEPTNO                 DNAME          
---------------------- -------------- 
40                     OPERATIONS     

1 rows selected

O query interno necessita devolver um valor que não tem que ser a coluna que está em causa. O exemplo anterior pode ser substituído por este:

select d.deptno, d.dname
from dept d
where not exists (select 1
                  from emp e
                  where e.deptno=d.deptno);
DEPTNO                 DNAME          
---------------------- -------------- 
40                     OPERATIONS     

1 rows selected

Uma consulta ao dicionário de dados mostra que o relacionamento entre as tabelas EMP e DEPT não está assegurado por uma restrição definida no motor da base de dados. Isto significa que é possível que exista um empregado que trabalhe num departamento que não esteja definido na tabela DEPT. A consulta abaixo pesquisa isso:

select e.empno, e.ename, e.deptno
from emp e
where not exists (select deptno
                  from dept
                  where dept.deptno=e.deptno);
EMPNO                  ENAME      DEPTNO                 
---------------------- ---------- ---------------------- 

0 rows selected

bthome.gifTopo


Realizado por Turtle Learning ®. Última alteração em 2011-08-14