Sunteți pe pagina 1din 6

BAZE DE DATE Laborator 5

INTEROGĂRI ÎN SQL SERVER


Principala operaţie efectuată într-o bază de date este operaţia de extragere a datelor, care se realizează cu ajutorul unei
clauze SELECT.

SELECT
Clauza SELECT are o sintaxă foarte complexă, dar, pe scurt, se poate folosi următoarea:

SELECT [DISTINCT] lista_coloane


[ INTO tabel_nou ]
FROM lista_tabele
[ WHERE predicat ]
[ GROUP BY lista_coloane ]
[ HAVING predicat ]
[ ORDER BY lista_coloane [ ASC | DESC ] ]

SQL pune la dispoziţie condiţii de joncţiune ce permit obţinerea de date din tabele diferite. Se pot folosi următoarele:

CROSS JOIN
Este echivalentul din standardul ANSI/ISO SQL: 1999 SQL pentru calcularea unui produs cartezian. Seturile de rezultate
reprezintă toate combinaţiile posibile de coloane din ambele tabele.

SELECT student.nume, student.prenume, note.nota


FROM note CROSS JOIN student

INNER JOIN
Permite folosirea de condiţii la joncţiune. Folosind clauza ON se permite folosirea clauzei WHERE pentru a restrânge
numărul de rânduri obţinute.

SELECT student.nume, student.prenume, note.nota


FROM note INNER JOIN student
ON note.cods=student.cods;

OUTER JOINS
În standardul ANSI-99 SQL, o joncţiune a două sau mai multe tabele care returnează doar rândurile corespondente se
numeşte joncţiune interioară. Dacă se returnează şi celelalte, se spune că avem o joncţiune exterioară. Se folosesc în sintaxă
termenii “left, full, şi right”, care fac referire la ordinea de apariţie a tabelelor în clauza FROM.

Left Outer Join


SELECT student.nume, student.prenume, note.nota
FROM note LEFT OUTER JOIN student
ON note.cods =student.cods;

Interogarea va întoarce toate rândurile corespondente, cât şi toate notele, chiar dacă acestea nu aparţin nici unui student.

Right Outer Join


SELECT student.nume, student.prenume, note.nota
FROM note RIGHT OUTER JOIN student
ON note.cods =student.cods;

Interogarea va întoarce toţi studenţii, chiar şi cei care nu au note.


BAZE DE DATE Laborator 5
Full Outer Join
SELECT student.nume, student.prenume, note.nota
FROM note FULL OUTER JOIN student
ON note.cods =student.cods;

Extrage atât rândurile corespondente cât şi celelalte din ambele tabele, adică se vor returna toate rândurile din ambele tabele
chiar dacă acestea nu au corespondent.

UNION
Acet operator combină rezultatele obţinute în urma execuţiei a două interogări într-unul singur. Permite combinarea
rezultatelor a două interogări într-un singur set de rezultate, respectând condiţiile:
a. fiecare interogare trebuie să aibă acelaşi număr de coloane şi să le listeze în aceeaşi ordine;
b. coloanele returnate de fiecare instrucţiune SELECT trebuie să fie compatibile la atribuire sau trebuie să fie transformate
explicit într-un tip de date compatibil la atribuire cu coloanele lor corespondente din celelalte instrucţiuni SELECT
c. combinarea coloanelor compatibile la atribuire, dar de tipuri diferite, produce o coloană de tipul cu cea mai mare
precedenţă dintre cele două (de exemplu, combinarea unei coloane de tip smallint cu o coloană de tip float produce o
coloană rezultat de tip float;
d. numele coloanelor returnate de UNION sunt derivate din cele din prima instrucţiune SELECT
e. UNION ALL este mai rapidă decât UNION deoarece ea nu elimină duplicatele înainte de returnate.

Operaţii semantice
FROM: permite afişarea produsului cartesian al listei_de_tabele
WHERE: aplică σpredicat
GROUP BY: grupează tuplurile corespunzător cu lista_de_grupare_pe_coloane
HAVING: aplică σpredicat grupurilor
SELECT: aplică πlista_de_iesire_a_coloanelor (păstrează duplicatele)
DISTINCT: elimină duplicatele
ORDER BY: ordonează rezultatul pe baza listei_de_ordonare_pe_coloane

Predicate
Un predicat este o expresie care returnează TRUE sau NOT TRUE. Ele se întâlnesc în clauzele WHERE sau HAVING ale
unei interogări.
Obs. S-a folosit NOT TRUE şi nu FALSE datorită problemelor de logică trivalentă – uneori nu se cunoaşte dacă o expresie
este falsă, tot ceea ce se ştie este că, cu siguranţă, nu este adevărată
Cele mai folosite predicate sunt:
BETWEEN – indică dacă o valoare dată se găseşte în intervalul închis definit de alte două valori
LIKE – testează dacă o valoare se află sau nu într-un şir model. Se pot folosi caracterele de înlocuire: “%” – procent
(corespunde oricărui număr de caractere) şi “ _” – underscore (corespunde unui singur caracter).
EXISTS – funcţie predicat care acceptă ca unic parametru o subinterogare. Dacă interogarea returnează un set de rezultate,
EXISTS întoarce valoarea TRUE, altfel întoarce valoarea FALSE
IN – oferă o metodă prescurtată de comparare a unei valori scalare cu fiecare element dintr-o listă.
ANY, ALL – lucrează exclusiv cu subinterogări. ANY, operează similar predicatului IN

GROUP BY
Această clauză se foloseşte pentru a grupa rândurile dintr-un tabel în seturi mai mici, pe baza unei condiţii de grupare.

SELECT cods, AVG(nota)


FROM note
GROUP BY cods;

HAVING
Să presupunem că se doreşte găsirea celei mai mari note acordate fiecărui student, dar numai a acelora care au mai mult de o
notă. Ce este greşit în această soluţie?
BAZE DE DATE Laborator 5
SELECT cods, MAX(nota)
FROM note
WHERE COUNT(*) > 1
GROUP BY cods;

Se poate folosi clauza HAVING la fel ca în cazul clauzei WHERE pentru a restrânge numărul de rânduri returnate de
interogare. Într-o interogare care foloseşte clauzele GROUP BY şi HAVING, rândurile sunt mai întâi grupate, după care se
afişează doar rândurile ce îndeplinesc condiţia din clauza HAVING. Clauza HAVING este folosită pentru a restrânge
numărul de grupuri returnate de clauza GROUP BY.

SELECT cods, MAX(nota)


FROM note
GROUP BY cods
HAVING COUNT(*) > 1;

Funcţii de grup (funcţii agregat)


Funcţiile de grup operează pe seturi de înregistrări furnizând un singur rezultat pe grup. Fiecare dintre funcţiile de mai jos
furnizează un singur rezultat:

MIN: folosită pe coloane ce păstrează orice fel de tipuri de date returnând valoarea minimă.
MAX: folosită pe coloane ce păstrează orice fel de tipuri de date returnând valoarea maximă.
SUM: folosită pe coloane ce păstrează valori numerice pentru a calcula suma valorilor din coloana respectivă.
AVG: folosită pe coloane ce păstrează valori numerice pentru a calcula media aritmetică a valorilor din coloana respectivă.
COUNT: întoarce numărul de rânduri.
VARIANCE: folosită pe coloane ce păstrează valori numerice pentru a calcula împrăştierea rezultatelor. De exemplu, dacă
media aritmetică a notelor dintr-o grupă la ultimul test este 82%, iar studenţii au înregistrat un scor între 40% şi 100%,
rezultatul obţinut folosind această funcţie este mai mare decât dacă scorul studenţilor ar fi fost cuprins între 78% şi 88%.
STDDEV: asemănător cu funcţia anterioară. Pentru două seturi de date care au aproximativ aceeaşi medie, cu cât
împrăştierea este mai mare cu atât deviaţia standard este mai mare.

Sintaxa:

SELECT coloana, functie_de_grup(coloana), ..


FROM tabel
WHERE predicat
GROUP BY coloana, ...;

Subinterogări
O clauză SELECT care este inserată în cadrul altei clauze SELECT este numită subinterogare. Subinterogarea se execută cu
scopul de a obţine informaţii necunoscute. Clauza exterioară foloseşte informaţiile obţinute prin subinterogare pentru a afla
ceea ce i se cere.
Subinterogarea se execută o singură dată, anterior, în memoria principală a sistemului.
Subinterogările se pot introduce în clauzele: WHERE, HAVING şi FROM.
Sintaxa:

SELECT lista_de_selectie
FROM tabel
WHERE expresie operator(SELECT lista_de_selectie
FROM tabel);

Clauza SELECT din paranteză este interogarea interioară sau subinteorgarea.


Reguli
Subinterogările oferă un mijloc de a baza o interogare pe o alta (imbricarea interogărilor). Trebuie respectate regulile:
a. lista de selecţie a unei subinterogări create cu ajutorul unui operator de comparare poate conţine doar o singură expresie
sau nume de coloană;
BAZE DE DATE Laborator 5
b. dacă clauza WHERE a unei interogări exterioare conţine numele unei coloane, aceasta trebuie să fie compatibilă din
punct de vedere al joncţiunii cu coloana din subinterogare;
c. tipurile de date ntext, text şi image nu sunt permise într-o subinterogare;
d. clauza DISTINCT nu poate fi utilizată în subinterogări ce conţin clauza GROUP BY;
e. într-o subinterogare nu poate fi utilizată clauza ORDER BY decât dacă s-a utilizat şi restricţia TOP;
f. o vedere creată pe baza unei subinterogări nu poate fi actualizată;

Obs. Construcţiile SELECT pot fi imbricate pe max. 16 nivele. O subinterogare diferă de operatorul de cuplare prin aceea
că rezultatul final conţine date doar de la ultimul tabel.

Există 2 tipuri de subinterogări:

Subinterogări ce furnizează ca rezultat un singur rând


Folosesc operatorii aritmetici specifici: (>, =, >=, < <>, <=) şi întorc doar un singur rând în urma execuţiei interogării
interioare.
Acestea:
ƒ Returnează un singur rând
ƒ Folosesc doar operatorii de comparare (=, >,>=, <, <=, <>)
Întotdeauna:
ƒ Interogarea interioară se introduce între paranteze rotunde
ƒ Interogarea interioară se plasează la dreapta operatorului de comparare.
De reţinut că:
ƒ Interogările interioară şi exterioară pot prelua date din tabele diferite.
ƒ Doar o singură clauză ORDER BY poate fi folosită într-o clauză SELECT şi, dacă apare, trebuie să se afle la
sfârşitul clauzei SELECT principale.

Subinterogări ce furnizează ca rezultat mai multe rânduri


Folosesc predicatele IN, ANY, ALL, SOME, EXISTS şi întorc ca rezultat mai multe rânduri din interogarea interioară. De
această dată nu se mai pot folosi operatorii de comparare. Operatorul NOT se poate folosi cu oricare dintre aceste predicate.
Dacă una dintre valorile returnate de o astfel de subinterogare este NULL, dar celelalte nu sunt:
ƒ Dacă se folosesc IN sau ANY, interogarea exterioară va returna doar rândurile corespunzătoare valorilor care nu
sunt NULL.
ƒ Dacă se foloseşte ALL interogarea exterioară nu va returna nimic, deoarece ALL compară un rând provenit din
interogarea exterioară cu fiecare valoare returnată de subinterogare, inclusiv cele NULL. Comparând ceva cu
NULL va rezulta tot NULL.
În continuare este prezentată sintaxa folosită în toate cele trei situaţii.

Varianta 1
Predicatele [ANY | SOME | ALL]
Această variantă este folosită atunci când se compară o valoare cu o altă valoare obţinută în urma folosirii unei
subinterogări. De exemplu, următoarea construcţie întoarce toţi studenţii (şi notele corespunzătoare acestora) care au cele
mai mari note.

SELECT Nume, Prenume, Nota


FROM Student INNER JOIN Note ON Student.Cods=Note.Cods
WHERE Nota = (SELECT Max(Nota) FROM Note);

ceea ce conduce la un rezultat diferit de varianta:

SELECT Nume, Prenume, MAX(Nota)


FROM Student INNER JOIN Note ON Student.Cods=Note.Cods
GROUP BY Nume, Prenume;

în care răspunsul corespunde întrebării: "Care este cea mai mare notă obţinută de fiecare student?"
Se observă faptul că, deoarece subinterogarea întoarce o singură valoare, nu este nevoie să se folosească nici unul dintre
predicatele ANY, SOME sau ALL. Următoarea construcţie prezintă toţi studenţii (şi notele corespunzătoare acestora) care
au note mai mari decât notele studentului Radu Tiberiu:

SELECT Nume, Prenume, Nota


BAZE DE DATE Laborator 5
FROM Student INNER JOIN Note ON Student.Cods=Note.Cods
WHERE Nota > All(
SELECT Nota
FROM Note INNER JOIN Student ON Student.Cods =Note.Cods
WHERE Nume = 'Radu' And Prenume='Tiberiu');

Se observă faptul că predicatele ANY şi SOME conduc la obţinerea aceluiaşi rezultat, returnând toate variantele ce respectă
condiţia de comparare pentru cel puţin una dintre valorile returnate de către subinterogare. De exemplu, dacă se înlocuieşte
ALL cu SOME în interogarea anterioară, rezultatul obţinut va conţine toţi studenţii (şi notele corespunzătoare acestora) care
sunt mai mari decât cea mai mică notă acordată studentului Radu Tiberiu.

Varianta 2
Predicatul [NOT] IN
Această variantă se foloseşte la căutarea unei valori a unei coloane dintr-un tabel rezultat în urma alteri interogări. De
exemplu, următoarea construcţie returnează toţi studenţii (şi notele corespunzătoare) din tabelul "Student" care nu apar în
tabelul "Note" (studenţii care nu au note):

SELECT Cods,Nume, Prenume


FROM Student
WHERE Cods NOT IN (SELECT Cods FROM Note);

Varianta 3
Predicatul [NOT] EXISTS
Această variantă se foloseşte atunci când se verifică dacă o anumită valoare există (este returnată) în urma executării
subinterogării. De exemplu, următoarea construcţie afişează toţi studenţii care nu au note:

SELECT Cods, Nume, Prenume


FROM Student
WHERE NOT EXISTS
(SELECT * FROM Note WHERE Note.Cods =Student.Cods);

Se observă faptul că tabelul "Note" este referit în subinterogare, ceea ce face ca SQL Server să evalueze subinterogarea câte
o dată pentru fiecare valoare a identificatorului "CodS" din tabelul "Note".

Observaţii de ansamblu
Atunci când se folosesc sintaxele 1 sau 2 subinterogarea trebuie să întoarcă o singură coloană. Altfel va apare un mesaj de
eroare.
Clauza SELECT interioară are acelaşi format şi reguli ca şi orice altă clauză SELECT, dar trebuie inclusă între paranteze
rotunde.

Exerciţii

1. Afişaţi notele obţinute de către studentul Radu Tiberiu.

2. Afişaţi taxele mărite cu 10%

3. Afişaţi numele şi prenumele studenţilor într-o singură coloană.

4. Afişaţi toţi studenţii care nu au prenumele Andrei.

5. Afişaţi numele şi prenumele studenţilor care au plătit taxe de peste 20 de lei, dar mai mici de
30 lei.

6. Afişaţi numele şi prenumele studenţilor care au primit note.

7. Afişaţi numele şi prenumele studenţilor din Braşov, Iaşi, Covasna

8. Reuniţi datele obţinute prin executarea a două interogări, astfel:


BAZE DE DATE Laborator 5
- Prima extrage numele şi prenumele studenţilor care au luat note mai mari de 7;
- A doua extrage numele şi prenumele studenţilor care au luat note de 5.

9. Câţi studenţi plătesc taxă?

10. Care este suma taxelor plătite de către toţi studenţii?

11. Afişaţi suma totală a plăţilor studentului Radu Tiberiu.

12. Care este cea mai mare taxă?

13. Cine are cea mai mare medie a notelor?

14. Câţi ani au trecut de la începutul studiilor fiecărui student?

15. Afişaţi cursurile urmate de către studentul Radu Tiberiu.

16. Afişaţi numele şi prenumele studenţilor, precum şi cursurile promovate cu note mai mari de
8.

17. Afişaţi numele şi prenumele studentelor care sunt la zi şi sunt bursiere.

18. Câte note are fiecare student? Furnizaţi numele şi prenumele lor.

19. Afişaţi media notelor obţinută de către fiecare student.

20. Afişaţi numele şi prenumele studenţilor care au primit note mai mari decât cea mai mică notă
acordată.

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