Sunteți pe pagina 1din 8

LABORATOR 7 SQL

Functii de grup si subinterogari


1. PARTE TEORETICA

1.1.AGREGAREA DATELOR FOLOSIND FUNCŢII DE GRUP

1.1.1. Funcţii de grup


Funcţiile de grup operează pe mai multe linii intorcând un rezultat. Se poate specifica un criteriu de grupare a
datelor cu clauza GROUP BY, pentru ca funcţiile de grup să întoarcă un rezultat pentru fiecare grup de linii. Din
acestă cauză,funcţiile de grup nu pot fi asociate în lista de coloane cu coloane individuale. Coloanele au valori
diferite pentru fiecare linie, iar funcţiile de grup se referă la un grup de linii. Se poate utiliza, însă în lista de coloane,
criteriul de grupare deoarece liniile au aceeaşi valoare pentru acesta.

Funcţiile de grup mai utilizate sunt: AVG, MIN, MAX, COUNT, SUM.

Funcţiile de grup ignoră valorile NULL. Excepţie face funcţia COUNT(*).

1.1.2. Comanda SQL


Sintaxa generală a comenzii este:
SELECT [criteriu,] funcţieGrup(expresie1)
FROM tabel
[WHERE condiţie]
[GROUP BY criteriu]
[HAVING expresie2]
[ORDER BY expresie]
unde:
- expresie reprezintă o expresie ce cuprinde coloane, deci are valori pentru fiecare linie a tabelului
specificat;
- criteriu reprezintă o listă de expresii;
- condiţie, reprezintă o expresie logică.

1.1.3. Descrierea funcţiilor de grup


AVG(expr) calculeaza valoarea medie a expresiei specificate ca argument, ignorând valorile null.
COUNT(expr) întoarce numărul de linii ce au valori diferite de null ale expresiei specificate ca argument.
COUNT (*) întoarce numărul de linii din tabelul specificat, inclusiv cele cu valori NULL în ele.
MAX(expr) calculeaza valoarea maximă a expresiei specificate ca argument, ignorând valorile null.
MIN(expr) calculeaza valoarea minimă a expresiei specificate ca argument, ignorând valorile null.
SUM(n) calculeaza suma valorilor expresiei specificate ca argument, ignorând valorile null.

Exemple:
1. Extragerea salariului minim, maxim şi mediu din tabelul “personal” se face cu comanda:
SELECT MIN(salariu), MAX(salariu), AVG(salariu)
FROM personal
Atenţie valorile NULL sunt ignorate.
2. Extragerea salariilor anuale minim, maxim şi mediu care iau în consideraţie şi sporul se face cu comanda:
SELECT MIN(salariu*(1+NZ(spor,0)),MAX(salariu*(1+NZ(spor,0)), AVG(salariu*(1+NZ(spor,0))
FROM personal
Deoarece o expresie care are un operand NULL are ca rezultat o valoare NULL, se utilizează funcţia
NZ(expr,val) care asociază valoarea specificată de al doilea argument valorilor NULL ale expresiei expr
dată ca prim argument.

3. Afişarea numărului de angajaţi din tabelul personal se face cu comanda:


SELECT COUNT(*) FROM personal;

1.1.4. Clauza GROUP BY


Clauza GROUP BY este utilizată pentru a specifica un criteriu de grupare a liniilor. Criteriul de grupare a
liniilor se referă la valori egale pentru criteriul specificat pentru liniile din acelaşi grup.
Criteriul se specifică printr-o listă de expresii care conţin coloane. O expresie este o coloană sau o expresie care
conţine coloane şi operatori şi funcţii asociate.
Exemple:
1. Sa se afişeze salariile minim, maxim, mediu pentru fiecare facultate:
SELECT id_facultate,MIN(salariu) AS Sal_minim, MAX(salariu) AS Sal_maxim, AVG(salariu) AS
Sal_mediu
FROM personal
GROUP BY id_facultate
2. Să se afişeze salariile maxime pentru fiecare funcţie:
SELECT functie,MAX(salariu)
FROM personal
GROUP BY functie
3. Sa se afişeze salariile maxime pentru fiecare funcţie pe facultate
SELECT id_facultate,functie,MAX(salariu)
FROM personal
GROUP BY id_facultate,functie

Imbricarea funcţiilor de grup


Funcţiile de grup se pot imbrica, adică se poate utiliza o funcţie de grup ca argument al altei funcţii de grup.
Exemplu: Să se afişeze salariul mediul cel mai mare din tabelul personal:
SELECT MAX(AVG(salariu)) FROM personal
Din păcate nu toate sistemele de gestiune implementează acestă imbricare, iar în SGBD Access nu este permisă
imbricarea funcţiilor.

Greşeala cea mai frecventă la utilizarea funcţiilor de grup este aceea de asociere a unei coloane (cu valori
individuale pe fiecare linie) cu o funcţie de grup în clauza SELECT. Exemplu:
SELECT nume, MAX(salariu) FROM personal;
Comanda este greşită deoarece coloana nume are valori diferite pentru fiecare linie, iar funcţia MAX întoarce o
valoare pentru toate liniile din tabel.

1.1.5. Filtrarea liniilor pentru funcţiile de grup


Filtrarea liniilor pentru funcţiile de grup se realizează cu clauza HAVING <expresieLogică>.
Spre deosebire de clauza WHERE sunt filtrare ieşirile funcţiilor de grup.
Intr-o comandă SELECT se pot utiliza ambele clauze: WHERE filtrează liniile înainte de aplicarea funcţiilor de
grup, iar HAVING liniile rezultat.
Exemplu:
Afişăm salariile muinime pe facultăţi mai mici decât 5000000:
SELECT id_facultate, MIN(salariu) FROM personal GROUP BY id_facultate HAVING
MIN(salariu)<5000000
Observaţie: În clauza HAVING se utilizează doar expresii valide pentru funcţiile de grup. Adică nu se pot
utiliza coloane cu valori individuale dacă nu sunt specificate în clauza GROUP BY.
Ordonarea liniilor întoarse se interogare se realizează cu clauza ORDER BY care poate include ca criterii de
ordonare funcţiile de grup şi criteriul de grupare.
Exemplu: Afişam salariile medii pe facultăţi în ordine descrescătoare a salariilor:
SELECT id_facultate, AVG(salariu)
FROM personal
GROUP BY id_facultate
ORDER BY AVG(salariu) DESC

1.2.SQL. SUBINTEROGĂRI

Subinterogările sunt interogări incluse în alte interogări. Rezultatul subinterogării, furnizat dinamic la execuţie, este
utilizat în interogare Subinterogarea se numeşte interogare interioară, iar interogarea în care se utilizează
interogare exterioară.
Clauzele în care se pot utiliza subinterogări sunt: WHERE, HAVING, FROM.

Subinterogările din clauzele WHERE, FROM sunt utilizate în operaţii de comparaţie astfel:
WHERE <expresie> <operator> (SELECT ……)

Subinterogarea este inclusă între paranteze.

1.2.1. Operatori de comparaţie


Subinterogările întorc valori. Acestea pot fi :
- o valoare pentru fiecare linie
- o mulţime de valori pentru fiecare linie
- o listă de valori corespunzătoare mai multor coloane.

Operatorii de comparaţie sunt:


- operatorii asociaţi tipurilor de date
- operatori pe mulţimi: IN, ANY(SOME), ALL
- operatorul EXIST de corelare a interogării exterioare cu cea interioară

Operatorii de comparaţie asociaţi tipurilor de date se utilizează pentru compararea cu o valoare nu cu o mulţime de
valori. În cazul utilizării lor, subinterogarea trebuie să întoarcă o singură valoare. Operatorii sunt: >, <, >=, <=, <>,
BETWEEN…AND…, LIKE
Exemple:
1. Afişaţi angajaţii cu salariul egal cu salariul minim din tabelul “personal”:
SELECT nume, salariu FROM personal WHERE salariu = (SELECT MIN(salariu) FROM personal)
2. Afişaţi salariile minime pe facultăţi mai mari decât salariul minim al facultăţii 2:
SELECT id_facultate,MIN(salariu) FROM personal GROUP BY id_facultate HAVING MIN(salariu) >
(SELECT MIN(salariu) FROM personal WHERE id_facultate=2)
3. Afişaţi angajaţii cu salariul mai mare sau egal decât al angajatului cu codul 3 şi funcţia egală cu cea a
angajatului 8.
SELECT nume, salariu FROM personal
WHERE salariu > (SELECT salariu FROM personal WHERE id_personal=3)
AND functie = (SELECT functie FROM personal WHERE id_personal=8)

1.2.2. Operatori pe mulţimi


Operatorii pe mulţimi sunt IN, <opcomparaţie> ANY, <opcomparaţie> ALL

Operatorul IN
Operatorul IN este utilizat pentru a compara un operand cu elemente unei mulţimi. Valoarea returnată este true dacă
operandul este egal cu unul din elementele mulţimii. Altfel răspunsul este false.
Exemplu: Afişaţi angajaţii cu salariul egal cu salariul minim din fiecare facultate:
SELECT nume, salariu, id_facultate
FROM personal
WHERE salariu IN (select MIN(salariu) FROM personal GROUP BY id_faculatate)

Operatorul <opcomparaţie> ANY


Operatorul ANY compară un operand cu fiecare element al unei mulţimi. Astfel:
 < ANY înseamnă < maxim
 ANY înseamnă > minim
 = ANY înseamnă IN
Exemplu: Afişaţi angajaţii din tabelul personal cu salariul mai mic decât al asisteţilor, care nu sunt asistenţi:
SELECT nume, salariu, functie
FROM personal
WHERE salariu <ANY (select salariu FROM personal WHERE UCASE(TRIM(functie))=”ASISTENT”)
AND UCASE(TRIM(functie))<>”ASISTENT”

Operatorul <opcomparaţie> ALL


Operatorul ALL compară un operand cu toate elementele unei mulţimi. Astfel:
 < ALL înseamnă < minim
 >ALL înseamnă > maxim
Exemplu: Afişaţi angajaţii din tabelul personal cu salariile mai mari decât salariile medii pe facultati:
SELECT nume, salariu, functie
FROM personal
WHERE salariu >ALL (select AVG(salariu) FROM personal GROUP BY id_facultate)

Operatorul EXISTS
Operatorul EXISTS testeazǎ existenţa elementelor unei mulţimi şi întoarce FALSE pentru o mulţime vidǎ şi TRUE
dacǎ mulţimea are elemente.
Exemplu: Afişaţi facultǎţile fǎrǎ angajaţi :
SELECT id_facultate, nume_facultate
FROM facultati AS f
WHERE NOT EXISTS (SELECT 1
FROM personal
WHERE id_facultate = f.id_facultate);

1.2.3. Subinterogări corelate


Subinterogǎrile corelate sunt subinterogǎri în care se utilizeazǎ valori obţinute din interogarea externǎ.
Exemplu : Afişaţi angajaţii cu salariul mai mare decât salariul mediu pe departament :
SELECT nume,salariu,id_facultate
FROM personal AS p
WHERE salariu > (SELECT AVG(salariu) FROM personal
WHERE id_facultate=p.id_facultate)

1.2.4. Subinterogări în clauza FROM


Subinterogǎrile se pot utiliza în clauza FROM, caz în care trebuie specificat alias-ul tabelului corespunzǎtor
subinterogǎrii:
Exemplu : Afişaţi angajaţii cu salariul mai mare decât salariul mediu pe departament :
SELECT p.nume, p.salariu, m.salmediu
FROM personal AS p, (SELECT id_facultate, AVG(salariu) AS salmediu
FROM personal GROUP BY id_facultate) AS m
WHERE p.id_facultate=m.id_facultate AND p.salariu>m.salmediu
Exemplu: Afişăţi funcţia cu cel mai mic salariu mediu
SELECT functie, AVG(salariu) FROM personal
GROUP BY functie
HAVING AVG(salariu) = (SELECT MIN(s.salmediu) FROM (select AVG(salariu) AS salmediu FROM
personal GROUP BY id_facultate) AS s)

2. PARTE PRACTICA

1. Afişaţi cel mai mare salariu pentru fiecare functie in ordinea descrescǎtoare a
salariilor.
SELECT functie, MAX(salariu)
FROM personal
GROUP BY functie
ORDER BY MAX(salariu) DESC;

2. Afişaţi totalul salariilor pe facultăţi si funcţii.


SELECT id_facultate,functie, SUM(salariu)
FROM personal
GROUP BY id_facultate,functie
ORDER BY id_facultate,functie

3. Afişaţi, în ordine descrescǎtoare dupǎ salariu, angajatii cu cel mai mare salariu pe
fiecare functie.
SELECT personal.nume,personal.functie,personal.salariu
FROM (SELECT functie,MAX(salariu) AS sal FROM personal
GROUP BY functie) AS t INNER JOIN personal ON
t.functie=personal.functie AND t.sal=personal.salariu
ORDER BY personal.salariu DESC

Comparati cu interogarea urmatoare:


SELECT nume, functie, salariu
FROM personal
WHERE salariu IN (SELECT MAX(salariu) FROM personal
GROUP BY functie)
ORDER BY salariu DESC
Obsevati diferenta! In prima interogare sunt afisati angajatii care au cel mai mare
salariu pe functie, iar in a doua interogare angajatii cu salarii egale cu salariile maxime
pe functii.

4. Afişaţi media salariilor anuale pe fiecare facultate in ordinea crescǎtoare a salariilor.


SELECT functie, AVG(salariu*(1+NZ(spor,0))*12)
FROM personal
GROUP BY functie
ORDER BY AVG(salariu*(1+NZ(spor,0))*12)

5. Afişaţi angajaţii cu salariul mai mare decât media salariilor pe fiecare functie.
SELECT nume,functie,salariu
FROM personal
WHERE salariu > ANY (SELECT AVG(salariu) FROM personal GROUP BY
functie)
ORDER BY salariu

6. Afişaţi ultimii angajati din fiecare facultate. Ordonati dupa data angajarii.
SELECT nume, id_facultate, data_angajare
FROM personal
WHERE data_angajare IN (SELECT MAX(data_angajare)
FROM personal
GROUP BY id_facultate)
ORDER BY data_angajare;

7. Afişaţi angajaţii cu salariul mai mare decât media salariilor pe functie.


SELECT nume, salariu, id_facultate
FROM personal AS p
WHERE salariu > (SELECT AVG(salariu)
FROM personal
WHERE id_facultate = p.id_facultate)
ORDER BY id_facultate;

8. Listati, folosind o subinterogare, toate facultǎţile care nu au angajati.


SELECT id_facultate, nume_facultate
FROM facultati AS f
WHERE NOT EXISTS (SELECT 1
FROM personal
WHERE id_facultate = f.id_facultate);

9. Afişaţi numărul de angajaţi ai fiecărei facultăţi.


SELECT id_facultate,COUNT(*)
FROM personal GROUP BY id_facultate

10. Afişaţi numele şi salariul angajatilor cu cele mai mari 3 salarii.


SELECT nume, salariu
FROM personal p
WHERE 3 > (SELECT COUNT(*)
FROM personal
WHERE p.salariu < salariu);

11. Afişaţi totalul salariilor pe fiecare funcţie pentru facultatea de “Stiinte Economice”.
SELECT functie, SUM(salariu)
FROM personal
GROUP BY id_facultate,functie
HAVING id_facultate = (SELECT id_facultate FROM facultati WHERE
UCASE(TRIM(nume_facultate))="STIINTE ECONOMICE")
ORDER BY id_facultate,functie

12. Afişaţi totalul taxelor pe specializari si facultati.


SELECT f.nume_facultate, sp.nume_spec,SUM(s.valoareTaxa)
FROM studenti as s, specializari AS sp, facultati AS f
WHERE s.id_spec=sp.id_spec AND sp.id_facultate=f.id_facultate
GROUP BY f.nume_facultate, sp.nume_spec
13. Afişaţi facultatea cu totalul cel mai mare al taxelor.
SELECT t.nume_facultate, MAX(totaltaxa)
FROM (SELECT f.nume_facultate, sp.nume_spec,SUM(s.valoareTaxa) AS
totalTaxa
FROM studenti as s, specializari AS sp, facultati AS f
WHERE s.id_spec=sp.id_spec AND sp.id_facultate=f.id_facultate
GROUP BY f.nume_facultate, sp.nume_spec) AS t
GROUP BY t.nume_facultate

14. Afişaţi numarul de studenti ai fiecărei facultăţi.


SELECT f.nume_facultate,COUNT(s.id_student)
FROM studenti as s, specializari AS sp, facultati AS f
WHERE s.id_spec=sp.id_spec AND sp.id_facultate=f.id_facultate
GROUP BY f.nume_facultate

15. Afişaţi numarul de studenţi fără taxă pe fiecare specializare.


SELECT f.nume_facultate,COUNT(s.id_student)
FROM studenti as s, specializari AS sp, facultati AS f
WHERE s.id_spec=sp.id_spec AND sp.id_facultate=f.id_facultate AND
s.valoaretaxa IS NULL
GROUP BY f.nume_facultate

16. Afisati numele angajatilor si gradul salariilor cele mai mici pe fiecare facultate.
SELECT nume, salariu,id_facultate FROM personal AS p WHERE salariu =
(SELECT MAX(salariu) FROM personal WHERE id_facultate=p.id_facultate);

17. Afisati functia cu cel mai mare total al salariilor anuale.


Deoarece Access nu implementeaza functii de grup imbricate, sunt necesare 2
interogari:
Prima interogare o salvam cu numele total_functii si va contine totalul salariilor
anuale pe fiecare functie:
SELECT functie, sum(salariu*(1+nz(spor)/100)*12) AS total FROM personal
GROUP BY functie;

A doua interogare afiseaza functia din total_functii cu cea mai mare suma a a
salariilor:
SELECT functie FROM total_functii WHERE total=(select max(total) From
total_functii);

18. Afisati numele facultatii cu media cea mai mare a salariilor.


Prima interogare “medie_facultati”:
SELECT nume_facultate, AVG(salariu) AS medie FROM personal, facultati WHERE
facultati.id_facultate=personal.id_facultate GROUP BY nume_facultate;
A doua interogare:
SELECT nume_facultate FROM medie_facultati WHERE medie=(SELECT
MAX(medie) FROM medie_facultati);

19. Afisati numarul de angajati femei si barbati si totalul corespunzator al salariilor.


SELECT COUNT(*),SUM(salariu),sex FROM personal GROUP BY sex;
20. Afisati media salariilor pe fiecare an calendaristic.
SELECT YEAR(data_angajare),AVG(salariu) FROM personal GROUP BY
YEAR(data_angajare);

21. Afisati angajatii care au salariul mai mare decat al lectorilor si nu sunt lectori.
SELECT * from personal WHERE salariu >ANY (SELECT salariu FROM personal
WHERE functie="lector") AND functie<>"lector"

22. Afisati functia care are totalul salariilor mai mare dacat totalul salariilor
conferentiarilor.
SELECT functie,SUM(salariu) FROM personal GROUP BY functie HAVING
SUM(salariu) > (SELECT SUM(salariu) FROM personal WHERE
functie="conferentiar")

23. Afisati procentele corespunzatoare ale totalului salariilor pe fiecare facultate.


Solutia are 2 interogari. Interogarea “suma_facultati”:
SELECT sum(salariu) AS st, id_facultate FROM personal GROUP BY id_facultate;
si interogarea:
SELECT Sum(salariu)/Sum(st) FROM personal, suma_facultati WHERE
personal.id_facultate=suma_facultati.id_facultate GROUP BY personal.id_facultate;

24. Afisati numarul de studenti fara taxa pe fiecare facultate.


SELECT nume_facultate,COUNT(id_student) FROM facultati,specializari,studenti
WHERE facultati.id_facultate=specializari.id_facultate AND
specializari.id_spec=studenti.id_spec AND valoaretaxa IS NULL GROUP BY
nume_facultate;

25. Afisati totalul taxelor pe fiecare facultate.


SELECT nume_facultate, SUM(valoaretaxa) FROM facultati, specializari, student
WHERE facultati.id_facultate=specializari.id_facultate AND
specializari.id_spec=studenti.id_spec GROUP BY nume_facultate;

26. Afisati facultatea cu cea mai mare suma a salariilor.


Prima interogare “suma_facultati”
SELECT SUM(salariu) AS suma, nume_facultate
FROM facultati, personal
WHERE facultati.id_facultate=personal.id_facultate
GROUP BY nume_facultate;

A doua interogare:
SELECT nume_facultate
FROM suma_facultati
WHERE suma=(SELECT MAX(suma) FROM suma_facultati);

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