Sunteți pe pagina 1din 11

1

SUBINTEROGARI

Obiective

Dupa parcurgerea acestei lectii, veti avea cunostintele


necesare pentru a realiza urmatoarele:
 Descrierea tipurilor de probleme pe care le pot rezolva
subinterogarile;
 Definirea subinterogarilor;
 Listarea tipurilor de subinterogari;
 Scrierea subinterogarilor single-row si multiple-row.

Scopul lectiei

În aceasta lectie se vor studia caracteristici mai avansate ale instructiunii


SELECT. Se pot scrie subinterogari în clauza WHERE a altei instructiuni SQL în
scopul obtinerii de valori bazate pe o valoare necunoscuta a unei conditii. Aceasta
lectie acopera atît subinterogarile single-row, cît si cele multiple-row.

Folosirea unei subinterogari


pentru a rezolva o problema

“ Cine primeste un salariu mai mare decît cel al lui Jones ? ”


Cerere principala

“ Ce angajat are un salariu mai mare decît Jones ?


Subinterogare
?

Folosirea unei subinterogari pentru a rezolva o problema

Sa presupunem ca doriti sa scrieti o interogare pentru a afla cine cîstiga un


salariu mai mare decît salariul lui Jones.
Pentru rezolvarea acestei probleme este nevoie de doua interogari: o interogare
pentru a afla ce salariu cîstiga Jones si o a doua pentru a determina cine cîstiga mai
mult decît aceasta suma.
2

Problema poate fi rezolvata combinînd aceste doua interogari, integrînd una


din cereri în cealalta.
O cerere inclusa sau subinterogare returneaza o valoare folosita de catre
interogarea exterioara sau principala. Folosirea unei subinterogari este echivalenta
executarii a doua cereri secventiale si folosirii rezultatului primei cereri ca valoare de
cautare pentru cea de a doua cerere.

Subinterogari
SELECT select_list
FROM table
WHERE expr operator
(SELECT select_list
FROM table);

 Subinterogarea (cererea interna) se executa o singura data


înaintea interogarii principale.
 Rezultatul subinterogarii este utilizat de catre cererea
principala (cererea externa).

Subinterogari

O subinterogare reprezinta o instructiune SELECT care este inclusa într-o


clauza apartinînd altei instructiuni SELECT. Se pot astfel construi instructiuni mai
puternice pornind de la instructiuni simple prin utilizarea subinterogarilor. Acestea pot
fi foarte folositoare în cazurile în care se doreste selectarea unor rînduri dintr-un tabel
cu o conditie care depinde de datele din tabelul propriu-zis.
Subinterogarile pot fi plasate în urmatoarele clauze SQL:
 WHERE;
 HAVING;
 FROM.
În sintaxa mai sus prezentata:
operator implica unul din urmatorii operatori de comparatie: >, =
sau IN.
Nota: Operatorii de comparare se împart în doua clase:
 operatori single-row : >, =, >=, <, <>, <=
 operatori multiple-row : IN, ANY, ALL.
Subinterogarea este deseori referita ca fiind o instructiune SELECT inclusa,
sub-SELECT sau instructiune SELECT interna. În general, subinterogarea se executa
prima, iar rezultatul este folosit pentru a finaliza conditia de cerere pentru interogarea
principala sau externa.
3

Utilizarea unei subinterogari


SQL> SELECT ename
2 FROM emp 2975
3 WHERE sal >
4 (SELECT sal
5 FROM emp
6 WHERE empno=7566);

ENAME
----------
KING
FORD
SCOTT

Utilizarea unei subinterogari

În figura anterioara, cererea interna determina salariul angajatului cu numarul


7566. Cererea externa preia rezultatul cererii interne si îl foloseste pentru a afisa toti
angajatii care cîstiga un salariu mai amre decît aceasta suma.

Orientari în utilizarea subinterogarilor

 Includerea subinterogarilor în paranteze.


 Plasarea subinterogarilor în partea dreapta a operatorului
de comparare.
 A nu se adauga clauza ORDER BY într-o subinterogare.
 Folosirea operatorilor single-row în subinterogari single-
row
 Folosirea operatorilor multiple-row în subinterogari
multiple-row

Orientari în utilzarea subinterogarilor


 O subinterogare trebuie sa fie inclusa între paranteze.
 O subinterogare trebuie sa apara în partea dreapta a unui operator de
comparare.
 Subinterogarile nu pot contine clauza ORDER BY. Pentru o instructiune
SELECT poate exista doar o singura clauza ORDER BY, iar daca aceasta
clauza este specificata, ea trebuie sa fie ultima clauza din instructiunea
SELECT principala.
 Subinterogarile folosesc doua clase de operatori de comparare: operatori
single-row si operatori multiple-row.
4

Tipuri de subinterogari

 Subinterogari single-row
Cerere principala
Subinterogare FUNCTIONAR (CLERK)

 Subinterogari multiple-row
Cerere principala
Subinterogare FUNCTIONAR (CLERK)
MANAGER

 Subinterogari multiple-column

Cerere principala
Subinterogare
FUNCTIONAR (CLERK) 7900
MANAGER 7698

Tipuri de subinterogari

 Subinterogari single-row : cereri care returneaza doar un rînd din


instructiunea SELECT interna
 Subinterogari multiple-row : cereri care returneaza mai mult de un rînd din
instructiunea SELECT interna
 Subinterogari multiple-column : cereri care returneaza mai multe coloane
din instructiunea SELECT interna.

Subinterogari single-row

 Returneaza doar un rînd


 Folosesc operatori de comparare single-row

Operator Semnificatie
= Egal cu

> Mai mare decît

>= Mai mare sau egal cu

< Mai mic decît

<= Mai mic sau egal cu

<> Diferit de
5

Subinterogari single-row

O subinterogare single-row este acea subinterogare care returneaza un singur


rînd din instructiunea SELECT interna. Acest tip de subinterogare foloseste un
operator single-row. Figura anterioara prezinta lista operatorilor single-row.
Exemplu:
Afisarea angajatilor care lucreaza pe acelasi post ca si angajatul ce are
numarul 7369.
SQL> SELECT ename, job
2 FROM emp
3 WHERE job=
4 (SELECT job
5 FROM emp
6 WHERE empno=7369);

ENAME JOB
--------------- ------------
JAMES FUNCTIONAR (CLERK)
SMITH FUNCTIONAR (CLERK)
ADAMS FUNCTIONAR (CLERK)
MILLER FUNCTIONAR (CLERK)

Executarea unei subinterogari single-row


SQL> SELECT ename, job
2 FROM emp
3 WHERE job = FUNCTIONAR
4 (SELECT job
5 FROM emp
6 WHERE empno = 7369)
7 AND sal >
8 (SELECT sal 1100
9 FROM emp
10 WHERE empno = 7876);

ENAME JOB
---------- ---------
MILLER CLERK

Executarea unei subinterogari single-row

O instructiune SELECT poate fi considerata ca un bloc de cereri. Exemplul de


mai sus afiseaza angajatii al caror post este acelasi cu cel al angajatului cu numarul
7369 si a caror salariu este mai mare decît cel al angajatului 7876.
Exemplul este format din 3 blocuri de cereri: o cerere exterioara si doua cereri
interne. Blocurile de cereri interne sînt primele executate, producînd rezultatele
cererii: FUNCTIONAR (CLERK), respectiv 1100. Blocul exterior de cereri este apoi
procesat si foloseste valorile returnate de catre cererile interne pentru a finaliza
propriile conditii de cautare.
6

Ambele cereri interne returneaza valori singulare (FUNCTIONAR si 1100),


astfel ca aceasta instructiune SQL este denumita o subinterogare single-row.
Nota: Interogarile exterioare si incluse pot prelua datele din tabele
diferite.

Utilizarea functiilor de grup într-o subinterogare


SQL> SELECT ename, job, sal
2 FROM emp 800
3 WHERE sal =
4 (SELECT MIN(sal)
5 FROM emp);

ENAME JOB SAL


---------- --------- ---------
SMITH CLERK 800

Utilizarea functiilor de grup într-o subinterogare

În interogarea principala pot fi afisate date prin utilizarea unei functii de grup
într-o subinterogare care sa returneze un singur rînd. Subinterogarea se va plasa între
paranteze si dupa operatorul de comparare.
Exemplul din figura precedenta afiseaza numele, postul si salariul tuturor
angajatilor al caror salariu este egal cu salariul minim. Functia MIN (functie de grup)
returneaza o singura valoare (si anume, 800), care este folosita de catre interogarea
principala.

Clauza HAVING în subinterogare

 Server-ul de ORACLE executa mai întîi subinterogarile


 Server-ul de ORACLE returneaza rezultatele catre clauza
HAVING a interogarii principale
SQL> SELECT deptno, MIN(sal)
2 FROM emp
3 GROUP BY deptno
4 HAVING MIN(sal) > 800
5 (SELECT MIN(sal)
6 FROM emp
7 WHERE deptno = 20);

Clauza HAVING în subinterogari


7

Subinterogarile pot fi folosite nu numai în clauza WHERE, dar si în clauza


HAVING. Server-ul de Oracle executa subinterogarea, returnînd apoi rezultatul catre
clauza HAVING a subinterogarii principale.
Instructiunea SQL prezentata în figura de mai sus are ca scop final afisarea
tuturor departamentelor la nivelor carora salariul minim are o valoare mai mare decît
valoarea salariului minim din cadrul departamentului 20.
DEPTNO MIN(SAL)
------------- ----------------
10 1300
30 950

Exemplu: Se cere sa se gaseasca postul avînd cel mai scazut salariu mediu:

SQL> SELECT job, AVG(sal)


2 FROM emp
3 GROUP BY job
4 HAVING AVG(sal) = (SELECT MIN(AVG(sal))
5 FROM emp
6 GROUP BY job);

Ce este în neregula cu instructiunea urmatoare?

SQL> SELECT empno, ename


2 FROM emp
3 WHERE sal =
4 (SELECT MIN(sal)
5 FROM emp
6 GROUP BY deptno);

Operator single-row avînd ca termen drept o subinterogare


multiple-row
EROARE:
ORA-01427: subinterogarea single-row returneaza mai mult de un rînd

nici un rînd nu este selectionat

Erori ce pot apare la folosirea subinterogarilor

O eroare obisnuita la folosirea subinterogarilor o reprezinta returnarea a mai


mult de un rînd de catre o subinterogare dorita a fi de tip single-row.
În instructiunea SQL din exemplul anterior, subinterogarea contine o clauza
GROUP BY – dupa numarul departamentului (deptno), care implica selectarea mai
multor rînduri, cîte unul pentru fiecare grup gasit. În acest caz, rezultatul
subinterogarii va consta di valorile 800, 1300 si, respectiv 950.
8

Interogarea externa preia rezultatele subinterogarii (800, 1300, 950) si le


foloseste în clauza WHERE. Clauza WHERE contine un operator egal ( = ), operator
single-row de comparare, care asteapta o singura valoare de partea sa dreapta.
Operatorul ‘ = ’ nu poate accepta mai mult de o valoare primita de la subinterogare si
astfel este generata eroarea.
Pentru a corecta eroarea, operatorul egal ( = ) trebuie înlocuit cu operatorul IN.

O astfel de instructiune functioneaza ?

SQL> SELECT ename, job


2 FROM emp
3 WHERE job =
4 (SELECT job
5 FROM emp
6 WHERE ename='SMYTHE');

Subinterogarea nu returneaza nici o valoare


nici un rînd nu este selectat

Probleme ce pot apare la utilizarea subinterogarilor

O problema obisnuita legata de subinterogari o constituie posibilitatea


neselectarii nici unui rînd de catre interogarea inclusa.
În ceea ce priveste instructiunea SQL de mai sus, subinterogarea contine o
clauza WHERE (ename = ‘SMYTHE’). Se presupune ca intentia este de a selecta
angajatul cu numele Smythe. Instructiunea pare a fi corecta, dar la executie nu se
selecteaza nici un rînd.
Problema este ortografierea gresita a cuvîntului Smythe. Nu exista nici un
angajat cu numele de Smythe. Astfel, subinterogarea nu va selecta nici un rînd.
Interogarea externa preia rezultatul subinterogarii (nul, în acest caz) si foloseste acest
rezultat în propria-i clauza WHERE. Interogarea externa nu gaseste nici un angajat
avînd cîmpul referitor la post de valoare nula si astfel nu returneaza nici un rînd.

Subinterogari multiple-row

 Selecteaza mai mult de un rînd


 Folosesc operatori multiple-row de comparare
Operator Semnificatie
IN Egal cu oricare din elementele listei
Compara valoarea cu fiecare valoare
ANY
returnata de subinterogare luata separat
Compara valoarea cu toate valorile
ALL
returnate de subinterogare
9

Subinterogari multiple-row

Subinterogarile care returneaza mai mult de un rînd se numesc subinterogari


multiple-row. În cazul subinterogarilor multiple-row se folosesc operatori multiple-
row, în locul celor single-row. Operatorul multiple-row necesita una sau mai multe
valori.
SQL> SELECT ename, sal, deptno
2 FROM emp
3 WHERE sal IN (SELECT MIN(sal)
4 FROM emp
5 GROUP BY deptno);

Exemplu:
Se cere sa se selecteze angajatii care cîstiga un salariu egal cu salariul minim
la nivel de departament.
Interogarea interna va fi prima executata producînd ca raspuns la cerere trei
rînduri: 800, 950, 1300. Blocul cererii externe este apoi procesat si foloseste valorile
returnate de catre interogarea inclusa pentru a-si finaliza propria conditie de cautare.
De fapt, interogarea principala este privita din perspectiva server-ului Oracle astfel:
SQL> SELECT ename, sal, deptno
2 FROM emp
3 WHERE sal IN (800, 950, 1300);

Utilizarea operatorului ANY în subinterogarile multiple-row


SQL> SELECT empno, ename, job 1300
2 FROM emp 800
3 WHERE sal < ANY 1100
4 (SELECT sal 950
5 FROM emp
6 WHERE job = 'CLERK')
7 AND job <> 'CLERK';

EMPNO ENAME JOB


--------- ---------- ---------
7654 MARTIN SALESMAN
7521 WARD SALESMAN

Subinterogari multiple-row (continuare)

Operatorul ANY (si operatorul SOME, sinonim acestuia) compara o valoare


cu fiecare valoare returnata de subinterogare. Exemplul de mai sus afiseaza angajatii
ale caror salarii sînt mai mici decît al oricarui functionar (clerk) si care nu sînt
functionari. Salariul maxim pa care îl cîstiga un functionar este $1300. Instructiunea
SQL afiseaza toti angajatii care nu sînt functionari, dar cîstiga mai putin de $1300.
< ANY înseamna mai mic decît maxim.
> ANY înseamna mai mare decît minim.
= ANY este echivalent cu operatorul IN.
10

Utilizarea operatorului ALL în subinterogarile multiple-row


SQL> SELECT empno, ename, job 1566.6667
2 FROM emp
3 WHERE sal < ALL 2916.6667 2175
4 (SELECT avg(sal)
5 FROM emp
6 GROUP BY deptno);

EMPNO ENAME JOB


--------- ---------- ---------
7839 KING PRESIDENT
7566 JONES MANAGER
7902 FORD ANALYST
7788 SCOTT ANALYST

Subinterogari multiple-row (continuare)

Operatorul ALL compara o valoare cu toate valorile returnate de o


subinterogare. Exemplul de mai sus afiseaza toti angajatii ale caror salarii sînt mai
mari decît salariile medii la nivel de departamente.. Cel mai mare salariu mediu al
vreunui departament este $2916.6667, asa ca interogarea va selecta acei angajati ale
caror salarii sînt mai mari decît $2916.6667.
> ALL înseamna mai mare decît maxim
< ALL înseamna mai mic decît minim
Operatorul NOT poate fi folosit cu operatorii IN, ANY si ALL.

REZUMAT

Subinterogarile sînt folositoare atunci cînd o cerere se


bazeaza pe valori necunoscute.
SELECT select_list
FROM table
WHERE expr operator
(SELECT select_list
FROM table);

Rezumat

O subinterogare este o instructiune SELECT inclusa într-o clauza a altei


instructiuni SQL. Subinterogarile sînt folositoare atunci cînd interogarea se
bazeaza pe criterii necunoscute.
11

Subinterogarile au urmatoarele caracteristici:


 Pot transmite un rînd de date instructiunii principale care contine un
operator single-row, precum: =, <>, >, >=, < sau <=;
 Pot transmite rînduri multiple de date instructiunii principale care
contine un operator multiple-row, precum: IN, ANY sau ALL;
 Sînt primele procesate de catre server-ul Oracle, iar clauzele WHERE
si HAVING folosesc rezultatele;
 Pot contine functii de grup.

Privire generala asupra lucrarii practice

 Creare de subinterogari pentru obtinerea de valori bazate


pe criterii necunoscute
 Folosire subinterogari pentru a determina ce valori apartin
unui set de date si nu altuia

Privire generala asupra exercitiilor

În aceasta lucrare practica se vor scrie interogari complexe folosind


instructiuni SELECT incluse.
Chestionare
Exista posibilitatea de a se dori ca, pentru început, sa fie creata interogarea
interna pentru întrebarile urmatoare. Fiti siguri ca ea ruleaza si produce datele
anticipate înainte de a codifica interogarea principala.

Exercitii:
1. Sa se scrie o interogare care sa afiseze numele angajatului si data angajarii pentru
toti angajatii din acelasi departament ca Blake. A se exclude Blake.
2. Sa se creeze o cerere pentru a afisa numarul angajatului si numele sau pemtru toti
angajatii care cîstiga mai mult decît salariul mediu. Sa se sorteze rezultatele în
ordinea descrescatoare a salariului.
3. Sa se scrie o cerere care va afisa numarul si numele angajatului pentru toti cei care
lucreaza într-un departament care detine cel putin un angajat al carui nume contine
litera ‘ T ‘. Salvati instructiunea într-un fisier denumit p6q3.sql.
4. Afisati numele angajatului, numarul departamentului si postul pe care lucreaza
acesta pentru toti angajatii al caror departament este situat în Dallas.
5. Afisati numele si salariul tuturor angajatilor subordonati lui King.
6. Afisati numarul departamentului, numele si postul tuturor angajatilor din
departamentul de vînzari (sales).
7. Modificati p6q3.sql pentru a afisa numarul, numele si salariul tuturor angajatilor
care cîstiga mai mult decît salariul mediu si, totodata, lucreaza într-un departament
care detine cel putin un angajat ce contine în numele sau litera ‘ T ‘. Salvati
fisierul ca p6q7.sql. Reexecutati interogarea.

S-ar putea să vă placă și