Sunteți pe pagina 1din 48

3.

1 EVOLUŢIE ŞI PERFORMANŢE

SQL este cel mai cunoscut limbaj de interogare şi exponent de seamă al


limbajelor din a IV-a generaţie. SQL are un caracter universal fiind implementat pe
toate tipurile de SGBD.

Impactul SQL:
 utilizatorii nespecialişti apreciază uşurinţa de înţelegere şi asimilare,
sunt mulţumiţi de posibilitatea de a consulta ei înşişi baza de date, fără
sprijin de specialitate.
 pentru programatorii profesionişti SQL oferă comenzi puternice pentru
dezvoltarea de aplicaţii ce utilizează bazele de date.
Istoricul SQL: E.F.Codd sugerează crearea unui sub-limbaj universal pentru
gestionarea BD.
Prima realizare practică: 1974, la IBM, proiectul unui SGBD denumit
System/R.
1974 - o lucrare a lui Chamberlin şi Boyce foloseşte denumirea SEQUEL
(Structured English as QUEry Language) pentru un limbaj structurat de interogare.
1980 - Don Chamberlin “prescurtează” denumirea SEQUEL în SQL -
Structured Query Language (limbaj structurat de interogare), denumire sub care
s-a consacrat.
În anii următori limbajul a fost perfecţionat, ajungând la sfârşitul anilor ’90
cel mai răspândit limbaj de interogare a BDR.

Pentru a asigura caracterul universal, a fost necesară standardizarea


limbajului. Standardele publicate de American National Standard Institute (ANSI)
s-au succedat astfel:
 SQL-86, în 1986, care a definit comenzile de bază ale SQL
 SQL-89, denumit şi SQL1, în 1989, care a constituit baza multor SGBDR-uri
comerciale
 SQL2, în 1992, cu multe completări necesare (dacă SQL1 se întindea pe 100
de pagini, SQL2 a fost publicat în aproape 600). SQL2 a fost standardul unanim
acceptat de majoritatea SGBD-urilor.
 SQL3, publicat în 1999 (2000 de pagini) este standardul curent, definit în ideea
de a transforma SQL într-un limbaj complet, capabil să definească şi gestioneze
obiecte complexe şi persistente.

Din perspectiva utilizatorului final, SQL îi oferă mijloacele necesare


pentru a extrage informaţiile dorite din baza de date. Utilizatorul poate formula o
consultare prin simpla descriere a rezultatului dorit.
Altfel spus, utilizatorul specifică rezultatul dorit, iar sistemul se ocupă de
procedura de căutare. SQL este cel mai reprezentativ limbaj de generaţia a IV-a,
orientată către utilizatorul final.
Principalele atuuri ale SQL sunt:
 independenţa de producător, nefiind o tehnologie "proprietară";
 portabilitate între diferite sisteme de operare;
 standardizare;
 este un limbaj de nivel înalt, cu o structură care se apropie de limba engleză
“curentă”;
 furnizează răspunsuri la interogări ad-hoc;
 permite multiple imagini asupra datelor bazei;
 constituie suportul programatic pentru accesul la BD;
 este un limbaj relaţional complet;
 permite definirea dinamică a datelor, în sensul modificării structurii bazei de
date aflată în utilizare.
3.2 COMENZI SQL

SQL acoperă întreaga gamă de operaţiuni care ţin de crearea şi întreţinerea


unei baze de date:
 definirea datelor;
 consultarea BD;
 actualizarea BD;
 controlul accesului la BD;
 partajarea BD între mai mulţi utilizatori;
 menţinerea integrităţii BD.
Principalele comenzi ale SQL, care se regăsesc, într-o formă sau alta, în
multe dintre SGBDR-urile actuale sunt:
Comenzi pentru manipularea și interogarea BD
SELECT Consultarea bazei de date
INSERT Adaugarea de noi linii într-o tabelă
DELETE Ştegerea de linii dintr-o tabelă
UPDATE Modificarea valorilor unor atribute
Comenzi pentru definirea bazei de date
CREATE TABLE Adăugarea unei noi tabele în BD
DROP TABLE Ştergerea unei tabele din bază
ALTER TABLE Modificarea structurii unei tabele
CREATE VIEW Crearea unei tabele virtuale
DROP VIEW Ştergerea unei tabele virtuale

Comenzi pentru controlul accesului la BD


GRANT Acordarea unor drepturi pentru utilizatori
REVOKE Revocarea unor drepturi pentru utilizatori
Comenzi pentru controlul tranzacţiilor
COMMIT Marchează sfârşitul unei tranzacţii
ROLLBACK Abandonează tranzacţia în curs
Totuşi, SQL nu este un limbaj de programare propriu-zis, dacă îl comparăm
cu Basic, Pascal, C sau COBOL. Până la SQL-3, nu au existat comenzile pentru
codificarea structurilor de control, esenţiale în scrierea de proceduri. De aceea, SQL
este referit în unele lucrări ca sub-limbaj orientat pe lucrul cu bazele de date.

Pe de altă parte, trebuie să precizăm că instrucţiuni scrise în SQL pot fi incluse


în programe redactate în alte limbaje de programare. Aplicaţii scrise în Visual Basic
sau Delphi realizează conectarea la baze de date şi apoi realizează operaţii de
actualizare sau consultare a acestora prin instrucţiuni elaborate în SQL.
3.3 COMENZI PENTRU DESCRIEREA DATELOR

Comanda CREATE TABLE creează o tabelă vidă (fără linii), cu o anumită


structură. De exemplu, pentru crearea tabelei CLIENTI, comanda se poate scrie
astfel:

CREATE TABLE CLIENTI


(NrLegitimatie integer not NULL,
NumeClient text(25) not NULL,
Adresa text(30),
CarteID text(9),
DataInscriere date,
NrCentru text(4) DEFAULT T001,
PRIMARY KEY (NrLegitimatie))

Atributul NrLegitimatie este de tip numeric, subtipul întreg. El este definit ca


şi cheie primară a relaţiei. Celelalte atribute conţin şiruri de caractere, mai puţin
DataInscriere care este dată calendaristică. Valorile pentru NrLegitimatie şi
NumeClient nu pot fi nule. Pentru NrCentru, valoarea implicită (pe care o ia
automat la adăugarea unei linii în tabela CLIENTI) este T001.
SQL permite atât declararea cheilor primare, cât şi a celor candidate şi a
cheilor străine.
Dacă stabilim că, pentru tabela CLIENŢI, cheia primară este atributul
CodClient, iar atributul CarteID este cheie alternativă, comanda se poate scrie
sub forma:
CREATE TABLE CLIENTI
(NrLegitimatie integer not NULL,
NumeClient text(25) not NULL,
Adresa text(30),
CarteID text(9),
DataInscriere date,
NrCentru text(4) DEFAULT T001,
PRIMARY KEY (NrLegitimatie)
UNIQUE (CarteID))

Cheile străine sunt declarate cu ajutorul opţiunii FOREIGN KEY. Considerăm


tabela CENTRE, în care cheia primară este atributul NrCentru.
CREATE TABLE CENTRE
(NrCentru text(4) not NULL,
Strada text(25),
Oras text(30),
Judet text(2),
CodPost text(7),
PRIMARY KEY (NrCentru))

Legătura între CLIENTI si CENTRE se face prin atributul NrCentru (cheie


primară în CENTRE şi cheie străină în CLIENTI către tabela CENTRE. Definiţia
tabelei CENTRE se modifică astfel:
CREATE TABLE CLIENTI
(NrLegitimatie integer not NULL,
NumeClient text(25) not NULL,
Adresa text(30),
CarteID text(9),
DataInscriere date,
NrCentru text(4) DEFAULT T001,
PRIMARY KEY (NrLegitimatie),
UNIQUE (CarteID),
FOREIGN KEY (NrCentru) REFERENCES CENTRE)

FOREIGN KEY (CODCL) REFERENCES CLIENTI


FOREIGN KEY (CODPROD) REFERENCES PRODUSE

Modificarea structurii unei tabele se referă la posibilitatea de a adăuga un nou


atribut la cele existente, de a şterge sau modifica proprietăţile sale. Operaţiunea
nu este atât de frecventă, fiind recomandabil să se desfăşoare cât mai rar.
Dacă în tabela CLIENTI se doreşte introducerea numărului de telefon al
clienţilor, este necesară adăugarea atributului NrTelefon, care este un şir de
caractere. Se utilizează comanda ALTER TABLE, astfel:
ALTER TABLE CLIENTI
ADD NrTelefon text(11)

Ştergerea unei tabele din baza de date se face cu DROP TABLE. Comanda
se utilizează de regulă pentru ştergerea tabelelor temporare, create pe parcursul
lucrului şi care nu trebuie păstrate în baza de date. Dacă am creat o tabelă
CLIENTI_CENTRE, necesară unor prelucrări deja încheiate, ştergerea ei se face
prin:
DROP TABLE CLIENTI_CENTRE
3.4 COMENZI PENTRU ACTUALIZAREA BAZELOR DE DATE

a) adăugarea de înregistrări,
b) ştergerea de înregistrări,
c) modificarea valorilor atributelor.

Adăugarea de înregistrări se face prin specificarea explicită a tabelei în


care se scrie şi a valorilor pentru noua înregistrare prin comanda INSERT. Nu este
obligatoriu să se precizeze numele câmpurilor, dacă ordinea acestora în tabelă este
cunoscută. Formatul este:
INSERT
INTO tabelă [(listă_câmpuri)]
VALUES (listă_valori)

Exemplu 1
Să se adauge un film nou în tabela FILME.
INSERT
INTO FILME
VALUES (10109, “Die Hard 3", "Actiune", 2003, ”R2000”, 5.5)

Execuţia comenzii de mai sus va genera o eroare, deoarece în structura


tabelei, câmpul PreInchir apare înainte de CodRegizor. Ordinea atributelor trebuie
cunoscută şi respectată! Pentru siguranţă, fraza INSERT de mai sus se poate scrie:
INSERT
INTO FILME (CodFilm, Titlu, Gen, An, CodRegizor, PretInchir)
VALUES (10109, “Die Hard 3", "Actiune", 2003, ”R2000”, 5.5)

Dacă la adăugarea unei linii nu se cunoaşte valoarea unui atribut, se foloseşte


valoarea <null>. Să spunem că nu se cunoaşte preţul cu care se va închiria filmul.
Comanda INSERT se scrie:
INSERT
INTO FILME (CodFilm, Titlu, Gen, An, CodRegizor, PretInchir)
VALUES (10109, “Die Hard 3", "Actiune", 2003, ”R2000”, NULL)

Ştergerea înregistrărilor se realizează prin comanda DELETE. Şi aici


trebuie specificat numele tabelei din care se şterge. Comada DELETE foloseşte
clauza WHERE pentru a selecta înregistrarea/înregistrările care vor fi şterse.
Formatul general este:
DELETE
FROM nume-tabelă
[WHERE condiţie]
Exemplu 2
Să se elimine din tabela SALARIATI înregistrarea pentru salariatul
cu marca 102.
DELETE
FROM SALARIATI
WHERE Marca = 102

Comanda DELETE se poate utiliza pentru a şterge toate liniile dintr-o tabelă.
Aşa cum se observă din format, clauza WHERE poate lipsi, deci comanda se aplică
tuturor înregistrărilor.
Utilitatea acestei comenzi vine atunci când ne permite ştergerea mai multor
înregistrări care îndeplinesc o condiţie.

Exemplu 3
Dacă firma noastră se reprofilează şi nu va mai închiria filme de
acţiune, acestea pot fi şterse din tabelă printr-o singură comandă:
DELETE
FROM FILME
WHERE Gen = “Actiune”

Modificarea valorilor unor atribute se face cu ajutorul comenzii UPDATE


care are formatul general:
UPDATE tabelă
SET atribut1 = expresie1 [,atribut2 = expresie2 …]
[WHERE condiţie]

Modificarea se poate face pentru valorile unuia sau mai multor atribute dintr-
o tabelă specificată, în una sau mai multe înregistrări.
Exemplu 4
Decizia de a creşte preţul de închiriere al filmelor de acţiune cu 2 RON
presupune modificarea atributului PretInchir în toate înregistrările în
care avem filme de acest gen. Operaţiunea se poate realiza elegant
printr-un singur UPDATE:
UPDATE FILME
SET PretInchir = PretInchir + 2
WHERE Gen = “Actiune”

Modificarea se poate face chiar în toate înregistrările, atunci când clauza


WHERE lipseşte.
Exemplu 5
Decizia de a creşte preţul de închiriere al tuturor filmelor cu un
procent de 10% presupune modificarea valorilor atributului
PretInchir în toate înregistrările. Operaţiunea se realizează de
asemenea elegant printr-un singur UPDATE:
UPDATE FILME
SET PretInchir = PretInchir + PretInchir*0.1
TESTUL DE LA CURS

Să se scrie comanda SQL pentru crearea unei tabele cu denumirea


BURSIERI2020, care să păstreze datele privind studenții care au primit bursă, cu
următoarea structură:
CNP (codul numeric personal),
MATRICOL (face legătura cu tabela DATEPERS),
MEDIE (media studentului),
TIPBURSA (tipul bursei: studiu, merit, sociala etc),
IBAN (contul bancar al studentului),
BANCA (banca la care are contul).
Se vor defini: cheia primară, cheia alternativă și cheia străină.

REZOLVARE:

CREATE T ABLE BURSIERI2020


(CNP TEXT(13) NOT NULL,
MATRICOL TEXT(6) NOT NULL,
MEDIE SINGLE,
TIPBURSA TEXT(20),
IBAN TEXT(24) NOT NULL,
BANCA TEXT(20)
PRIMARY KEY(CNP),
UNIQUE(IBAN),
FOREIGN KEY MATRICOL REFERENCES DATEPERS)
3.5 COMENZI PENTRU INTEROGAREA BAZELOR DE DATE

3.5.1 FRAZA SELECT

În SQL o interogare se formulează printr-o frază SELECT. O frază SELECT


consultă una sau mai multe tabele, din care extrage într-o tabelă-rezultat coloanele
specificate, incluzând liniile care verifică o expresie logică (condiţie) specificată. I
se spune “frază” şi nu comandă, deoarece include mai multe clauze: SELECT, FROM
şi WHERE. Într-o definiţie bazată pe algebra relaţională, semnificaţia acestor clauze
este următoarea:
 SELECT corespunde operatorului proiecţie şi desemnează coloanele care
vor apare în tabela-rezultat;
 FROM corespunde operatorului produs cartezian între tabelele din care
vor fi extrase datele;
 WHERE corespunde operatorului selecţie şi specifică predicatul selectiv al
algebrei relaţionale, altfel spus condiția
La modul general, o consultare SQL se scrie:

SELECT C1, C2, ..., Cn


FROM T1, T2, ..., Tm
[ WHERE P ]
C1, C2,… - coloanele (atribute sau expresii din mai multe atribute) din tabela-
rezultat
T1, T2,… - tabelele care sunt consultate
P - este predicatul dat de condiţia care trebuie verificată pentru ca liniile să
fie incluse în tabela-rezultat

Clauza WHERE apare între paranteze drepte deoarece poate lipsi, caz în care
toate liniile rezultate din tabelele consultate sunt incluse în tabela-
rezultat.
Exemplu 1
Se dă tabela SALARIATI.

Care sunt salariaţii angajaţi la centrul T001 ?

SELECT Marca, NumeSal  PROIECȚIE (se aleg 2 coloane)


FROM SALARIATI
WHERE NrCentru=”T001”  SELECȚIE (se aleg anumite linii)

Rezultatul:

Dacă scriem:
SELECT NrCentru, Marca, NumeSal
FROM SALARIATI
Obţinem o tabelă cu toţi salariaţii, de la toate centrele.

Atunci când se doreşte includerea în tabela-rezultat a tuturor coloanelor, se


foloseşte simbolul *, în loc să se enumere toate coloanele.

Exemplu 3
Care sunt filmele din anul 2020 pe care le avem?

SELECT *
FROM FILME
WHERE An = 2020
3.5.2 Precizări despre tipurile de date și scrierea de condiții de selecție

La formularea condiţiilor de selecţie, trebuie să se respecte tipul datelor,


deoarece valorile de tip text trebuie scrise între ghilimele, iar datele
calendaristice între două caractere # (valabil în Access – în alte SGBD-uri
se folosesc alte convenţii).
Spre exemplu, câmpul AN din tabela FILME l-am definit de tip numeric și am
scris condiția
WHERE An = 2020

WHERE An >=2018

Dacă îl defineam de tip text, condiţia din exemplul de mai sus s-ar fi scris
WHERE An = "2020"

Pentru datele calendaristice (tipul Date) în ACCESS se folosește caracterul #


La baza de date VÂNZĂRI, dacă dorim să afișăm doar comenzile din ziua de
20 octombrie 2019 scriem astfel comanda:

SELECT *
FROM COMENZI
WHERE Datacom = #10/20/2019#

Ținem seama și de formatul datei, care aici a fost luna/ziua/anul

Pentru datele de tip logic (tipul Yes/No) condiția este asumată prin
denumirea câmpului, folosind negația NOT pentru cazul când vrem valorile
NO/FALSE. Dacă vrem să vedem comenzile care au fost livrate scriem:

SELECT *
FROM COMENZI
WHERE Livrat

Comenzile care NU au fost livrate le vedem dacă scriem:

SELECT *
FROM COMENZI
WHERE NOT Livrat
3.5.3 Tabela-rezultat

Aşa cum am precizat, rezultatul execuţiei unei fraze SELECT se regăseşte


într-o tabelă-rezultat.
Dacă nu se precizează altfel, aceasta este o tabelă temporară, denumită
view. Ea nu se salvează și dispare când este închisă.
Cu ajutorul opţiunii INTO TABLE rezultatul interogării va fi inclus într-o
tabelă propriu-zisă, care va fi salvată și inclusă în baza de date.
Exemplu 4
Să se obţină o tabelă cu produsele din depozitul 1. Rezultatul va fi o
tabelă nouă în baza de date, denumită PROD_DEP1.
SELECT *
FROM PRODUSE
WHERE CodDep = 1
INTO TABLE PROD_DEP1

In ACCESS se scrie:
SELECT * INTO PROD_DEP1
FROM PRODUSE
WHERE CodDep = 1

La execuție se anunță crearea unei tabele noi.


3.5.4. Obținerea de coloane noi prin calcul

In tabela-rezultat coloanele pot fi câmpuri din tabelele interogate, dar şi


expresii calculate pe baza acestora. Numele acestor coloane în tabela-rezultat
conţin expresia (spre exemplu, cantitate*pret sau cant1+cant2 sau valoare/cant),
de aceea se utilizează opţiunea AS pentru schimbarea numelui coloanelor care
conţin expresii. Dacă nu se folosește AS în denumirea coloanei apare Expr...

Exemplu 5
Să se afișeze valorile în Euro pentru facturi.
SELECT Nrfact, ValcuTVA/4.87 AS ValEUR
FROM Facturi

Se poate utiliza AS și pentru a redenumi un câmp, ca în exemplul


următor:
SELECT Denprod, UM AS UnitateMasura, Stoc
FROM PRODUSE
3.5.5 Clauza DISTINCT (eliminarea dublurilor)

Spre deosebire de algebra relaţională, unde prin proiecţie se elimină tuplurile


identice, în SQL nu se elimină automat dublurile din tabela-rezultat. În acest
scop se utilizează opţiunea DISTINCT înainte de numele câmpului care poate
prezenta valori care se repetă.
“care sunt funcţiile pe care avem angajaţi la firmă?”

Exemplu 6
Să se afișeze codurile produselor comandate.
SELECT DISTINCT Codprod
FROM COMENZI

În absența clauzei DISTINCT:


SELECT Codprod
FROM COMENZI

Duce la lista de mai jos...


TESTUL DE LA CURS

Se dă tabela
BURSIERI2020(CNP, Matricol, Medie, TipBursa, IBAN, Banca).

Să se scrie comenzile SQL pentru a obține:


1. o listă cu studenții care au bursă de merit.
SELECT *
FROM BURSIERI2019
WHERE tipbursa = "merit"
2. o listă cu studenții care au medii mai mari sau egale cu 9.50.
SELECT *
FROM BURSIERI2019
WHERE medie >= 9.5
3. o listă cu studenții care au media 10, care să conțină numărul
matricol și tipul bursei obținute.
SELECT matricol, tipbursa
FROM BURSIERI2019
WHERE medie = 10
4. o listă care să conțină CNP, IBAN și Banca doar pentru bursa
sociala.
SELECT cnp, iban, banca
FROM BURSIERI2019
WHERE tipbursa = "sociala"
5. o listă cu băncile la care se vor plăti bursele.
SELECT DISTINCT BANCA
FROM BURSIERI2019
3.6 UTILIZAREA OPERAŢIILOR ASAMBLISTE DIN ALGEBRA RELAŢIONALĂ

Operaţiile asambliste (reuniune, intersecţie, diferenţă, produs cartezian) pot


fi realizate în SQL prin intermediul unor operatori specifici.
Reuniunea se realizează cu operatorul UNION. Desi SQL nu elimină
automat dublurile, în cazul reuniunii, folosirea operatorului UNION asigură
înlăturarea liniilor identice din tabela-rezultat. La modul general, reuniunea a două
relaţii R1 şi R2 se scrie:
SELECT *
FROM R1
UNION
SELECT *
FROM R2

Intersecţia foloseşte operatorul INTERSECT:


SELECT *
FROM R1
INTERSECT
SELECT *
FROM R2

Diferenţa se realizează utilizând operatorul MINUS:


SELECT *
FROM R1
MINUS
SELECT *
FROM R2

Aceste operaţii sunt deosebit de utile la reorganizarea bazelor de date, atunci


când se preiau date din mai multe tabele. Dacă operatorul UNION este implementat
în majoritatea SGBD-urilor, multe dintre acestea nu dispun nici de operatorul
INTERSECT, nici de MINUS, funcţiunea lor fiind asigurată prin combinarea altor
operatori, precum IN sau EXISTS.
Despre produsul cartezian am vorbit deja, arătând că se realizează prin
clauza FROM a unei fraze SELECT (nu există un operator explicit). Astfel, dacă în
clauza FROM apar două relaţii, R1 şi R2, atunci, în lipsa unei condiţii de joncţiune
formulată explicit, tabela-rezultat va conţine liniile obţinute din produsul cartezian
R1  R2.
SELECT *
FROM R1, R2
Desigur, produsul cartezian este utilizat cu sens atunci când este urmat de o
selecţie. Mai pe scurt, atunci când are loc joncţiunea dintre cele două relaţii.
Baza de date utilizată în exemple:

SALARIATI(Marca, Nume, Functie, SalOra, NrCentru)


CENTRE(NrCentru, Adresa, Oras, Judet, CodPost)
ORELUCRATE(Marca, NrCentru, OrePeSapt)
FILME(CodFilm, Titlu, Gen, An, PretInchir, CodRegizor)
REGIZORI(CodRegizor, Nume, Tara)
ACTORI(CodActor, Nume)
ROLURI(CodActor, CodFilm, Personaj)
3.7 REALIZAREA OPERAŢIILOR RELAŢIONALE

Vom prezenta în continuare operaţiile specifice modelului relaţional: selecţie,


proiecţie şi joncţiune, la care se apelează cel mai frecvent pentru consultarea unei
baze de date. Reamintim specificul celor 3 operații relaționale, implementate în
SQL în imaginea de mai jos.

3.7.1 Selecţia. Utilizarea operatorilor de comparare

Prin selecţie se filtrează înregistrările dintr-o tabelă, reţinându-se în tabela-


rezultat doar înregistrările care respectă condiţia specificată. În SQL, condiţia de
filtrare este specificată în clauza WHERE şi este construită cu ajutorul operatorilor
de comparare (=, <, >, <=, >=, <>), iar dacă predicatul constă din două sau
mai multe condiţii se vor utiliza operatorii logici AND sau OR.
Exemplu 1
Care sunt filmele de acţiune pe care le putem oferi clienţilor?
Tabela în care se află rezultatul şi asupra căreia se aplică predicatul de
selecţie este FILME. Predicatul este Categorie = "Actiune". Fraza SELECT
va avea forma:
SELECT *
FROM FILME
WHERE Gen = "actiune"
Rezultat:
CodFilm Titlu Gen An PretInchir CodRegizor
10011 Ronin Actiune 1998 3.5 R1011
10018 The Fifth Element Actiune 1997 3.5 R1013
10101 16 Blocks Actiune 2006 5.5 R1020
Exemplu 2
Care sunt filmele de acţiune de după 2004 pe care le putem oferi
clienţilor?
SELECT *
FROM FILME
WHERE Gen = "actiune" AND An>=2004
Rezultat:
CodFilm Titlu Gen An PretInchir CodRegizor
10101 16 Blocks Actiune 2006 5.5 R1020

- operatorul AND a fost utilizat pentru a introduce un "ŞI" logic


- operatorul OR se utilizează pentru “SAU” logic.

Care dintre ieșirile care au fost facturate au valoare mai mare de 1000
lei?
SELECT *
FROM IESIRI
WHERE Facturat AND Valoare>=1000
Care sunt facturile încasate prin bancă în ziua de 4 noiembrie?
SELECT *
FROM INCASARI
WHERE ModPlata = ”banca” AND DataInc = #11/4/2019#
Care sunt facturile pe care clientul cu codul 200 le-a plătit la livrare?
SELECT *
FROM FACTURI
WHERE Codcl = 200 AND TermenPl = 0

Exemplu 3
Care sunt filmele din 2006 din categoria “acţiune” sau “dramă”?
SELECT *
FROM FILME
WHERE An = 2006 AND (Gen = "Actiune" OR Gen = “Drama”)
Rezultat:
CodFilm Titlu Gen An PretInchir CodRegizor
10101 16 Blocks Actiune 2006 5.5 R1020
10204 Forrest Gump Drama 2006 7.5 R1028
Care sunt clienții din județele Arad și Timiș care sunt din prima
categorie (cod maxim 199)?
SELECT *
FROM CLIENTI
WHERE Cod <= 199 AND (Judet = "tm" OR Judet = “ar”)
Importanta parantezelor!!
Dacă s-ar scrie fără paranteze:

WHERE Cod <= 199 AND Judet = "tm" OR Judet = “ar”

 cei din TM care au cod mai mic de 199 SAU toti clientii din AR (pentru
ei nu se mai verifică și prima condiție...)

În SQL, pentru comparare, în afara operatorilor "clasici" specificaţi mai sus,


pot fi utilizaţi şi alţi operatori, dintre care îi vom descrie pe următorii:
 BETWEEN (între, cuprins între)
 LIKE (ca şi, la fel ca)
 IN (în)
 IS NULL (este nul)
Operatorul BETWEEN permite specificarea unui interval de valori în care
trebuie să se încadreze câmpul/expresia testată. Acest operator se poate utiliza
doar pentru date numerice sau date calendaristice.

Exemplu 4
Care sunt filmele de acţiune apărute între 1997 şi 1999?
Fără operatorul BETWEEN am scrie:
SELECT *
FROM FILME
WHERE gen = "Actiune" AND An>=1997 AND An<=1999
Sau
SELECT *
FROM FILME
WHERE gen = "Actiune" AND (An=1997 OR An=1998 OR An=1999)

Operatorul BETWEEN permite o formulare mai elegantă:


SELECT *
FROM FILME
WHERE gen = "Actiune" AND An BETWEEN 1997 AND 1999
Rezultat:
CodFilm Titlu Gen An PretInchir CodRegizor
10011 Ronin Actiune 1998 3.5 R1011
10018 The Fifth Element Actiune 1997 3.5 R1013

Care sunt facturile din perioada 1-7 noiembrie cu valoare între 200 și 500 lei?

SELECT *
FROM FACTURI
WHERE DataFact BETWEEN #11/1/2019# AND #11/7/2019#
AND ValFact BETWEEN 200 AND 500

Operatorul LIKE se foloseşte pentru câmpurile de tip text, pentru a


compara valorile acestora cu un literal (o constantă de tip text).
În definirea şirului de caractere respectiv se folosesc litere, cifre, dar şi
caractere speciale, care au semnificaţii aparte. Unul dintre cei mai cunoscuţi este
caracterul *, denumit specificator multiplu sau joker, deoarece înlocuieşte un
număr nespecificat de caractere. O descriere simplă pentru * este “orice”.
Spre exemplu, dacă se doreşte obţinerea unei liste care să conţină numai
actorii al căror nume începe cu litera A, putem scrie condiţia din clauza WHERE sub
forma: NumeActor LIKE "A*". Se vor extrage din tabela ACTORI toate liniile pentru
care valoarea atributului NumeActor începe cu litera A, indiferent de lungimea
acestuia (ex. Al Pacino, Andy Garcia etc.).
Un alt caracter special utilizat în unele versiuni SQL (precum cea din ACCESS)
este caracterul  care substituie un singur caracter.
 înlocuieşte (substituie) un singur caracter
* înlocuieşte un şir de caractere de lungime variabilă
Cei doi specificatori pot fi utilizaţi şi împreună.
Spre exemplu, dacă se doreşte obţinerea unei liste care să conţină numai
actriţele al căror prenume este Julia, iar numele are 6 caractere, scriem condiţia
astfel: NumeActor LIKE "Julia ??????". În tabela-rezultat va apare Julia Ormond,
nu şi Julia Roberts, al cărei nume are lungimea de 7 caractere.

Exemplu 5
Care sunt filmele în titlul cărora apare cuvântul “Man”?
SELECT *
FROM FILME
WHERE Titlu LIKE "*Man*"
Rezultat:
CodFilm Titlu Gen An PretInchir CodRegizor
10013 RainMan Drama 1988 5.5 R1019
10102 Man of the year Comedie 2006 5.5 R1019

Care sunt clienții al căror nume începe cu A?

SELECT *
FROM CLIENTI
WHERE Nume LIKE "A*"

Operatorul IN se utilizeaza în formatul general:


expresie1 IN (valoare1, valoare2, ...)
Rezultatul evaluării unui predicat ce conţine acest operator va fi "adevărat"
dacă valoarea expresiei1 este egală cu (cel puţin) una din valorile: valoare1,
valoare2, ...
Operatorul este util dacă avem o listă de valori posibile pentru un câmp.
Exemplu 6
Care sunt filmele din anii 1994, 1998, 2001 şi 2004?
Fără operatorul IN am scrie:
SELECT *
FROM FILME
WHERE An=1994 OR An=1998 OR An=2001 OR An=2004
Operatorul IN simplifică formularea:
SELECT *
FROM FILME
WHERE An IN (1994, 1998, 2001, 2004)
Rezultat:
CodFilm Titlu Gen An PretInchir CodRegizor
10011 Ronin Actiune 1998 3.5 R1011
10099 Leon Drama 1994 5.5 R1013
10045 Meet the Fockers Comedie 2004 5.5 R1012

De precizat că operatorul se poate utiliza atât pentru datele numerice (ca mai
sus), cât şi pentru texte sau date calendaristice. Spre exemplu, se poate căuta
valoarea lui CodActor într-o listă prin CodActor IN ("A118", "A119", "A120").

Care sunt comenzile clienților 200, 222 sau 300 care au cantitate mai mare de 50?
SELECT *
FROM COMENZI
WHERE Cantitate > 50 AND Codcl IN (200,222,300)

Operatorul IS NULL ne permite să determinăm valorile nule dintr-o tabelă.


Aşa cum ştim, o valoare înseamnă o valoare nedefinită. Este posibil ca la adăugarea
unei noi înregistrări într-o tabelă, valorile unor atribute să fie necunoscute. Dacă
acele câmpuri nu sunt completate, valoarea câmpului pe linia respectivă este
<null>.
Pentru a vedea liniile cu date lipsă, se poate folosește operatorul IS NULL.

Exemplu 7
Să se afişeze lista filmelor pentru care NU s-a introdus anul lansării.
SELECT *
FROM FILME
WHERE An IS NULL
 Observaţie:
Valoarea <null> nu se confundă cu valoarea zero (pentru câmpurile
numerice) sau cu "spaţiu" (pentru câmpurile de tip text). <null> înseamnă o
valoare necunoscută. A nu se înţelege că trebuie să scriem <null> când
introducem datele. Simpla necompletare a unui câmp va însemna că
respectivul are valoarea <null>.

Care sunt clienții care au adresa de email?

SELECT *
FROM CLIENTI
WHERE email IS NOT NULL

3.7.2 Proiecţia

Prin proiecţie se reţin doar unele coloane din tabelele interogate. Coloanele
tabelei-rezultat sunt specificate în clauza SELECT separate prin virgulă.
Dacă se preiau toate coloanele, se foloseşte *. Dacă sunt mai multe tabele
(FILME şi REGIZORI), se va scrie:

SELECT FILME.*, REGIZORI.*

Referirea nume_tabelă.nume_câmp este necesară atunci când este vorba


de un câmp care apare în ambele tabele interogate. Spre exemplu, pentru a obţine
o listă cu numele filmului, numele actorului din rolul principal şi personajul jucat,
avem nevoie de date din trei tabele: FILME, ACTORI şi ROLURI. Totuşi, scriem
simplu:
SELECT Titlu, NumeActor, Personaj
deoarece aceste trei câmpuri nu apar decât într-o tabelă fiecare.
Dacă dorim ca lista să cuprindă cod film, titlu, cod actor, nume şi personaj,
va trebui să explicăm despre care CodFilm este vorba: cel din FILME sau cel din
ROLURI? La fel pentru CodActor, care apare în toate cele trei tabele interogate.
Clauza SELECTse va scrie:

SELECT FILME.CodFilm, Titlu, ROLURI.CodActor, NumeActor, Personaj

Un alt aspect important legat de proiecţie porneşte de la faptul că SQL nu


elimină dublurile automat. De aceea, dacă se doreşte ca în tabela-rezultat valorile
unei coloane să figureze o singură dată, se utilizează opţiunea DISTINCT .
Exemplu 8
În ce oraşe avem deschise centre de închiriere?
SELECT DISTINCT Oras
FROM CENTRE
Rezultat:
Oras
Timisoara
Cenad

În fine, precizăm opţiunea de ordonare a liniilor din tabela-rezultat după


valorile unui câmp specificat. Pentru aceasta se utilizează clauza ORDER BY.

Exemplu 9
Să se obţină lista filmelor pe care le avem, ordonate după anul
apariţiei.
SELECT Titlu, gen, an
FROM FILME
ORDER BY An
Rezultat:
Titlu Gen An
RainMan Drama 1988
The Firm Drama 1993
Leon Drama 1994
The Fifth Element Actiune 1997
Ronin Actiune 1998
Eyes Wide Shut Drama 1999
Cold Mountain Drama 2003
Meet the parents Comedie 2003
Meet the Fockers Comedie 2004
Moartea Dlui Lazarescu Drama 2005
The Interpreter Drama 2005
16 Blocks Actiune 2006
Failure to launch Comedie 2006
Man of the year Comedie 2006

Ordonarea liniilor tabelei-rezultat se poate face şi după mai multe câmpuri:


se ordonează după primul şi, la valori egale ale primului, ordinea este dată de
valorile celui de-al doilea. Pentru a ordona descrescător se foloseşte opţiunea
DESCENDING. Opţiunea ASCENDING nu trebuie precizată explicit, deoarece este
implicită.
Exemplu 10
Să se obţină lista filmelor pe care le avem, ordonate după anul apariţiei,
începând cu cele mai recente, apoi după gen şi titlul filmului.
SELECT *
FROM FILME
ORDER BY An DESCENDING, Gen, Titlu

Prioritatea de sortare este stabilită prin ordinea atributelor


specificate în ORDER BY: prima ordonare se face după valorile anului;
toate filmele din acelaşi an sunt apoi ordonate pe genuri, iar cele de acelaşi
gen apar în ordine alfabetică.

Rezultat:
CodFilm Titlu Gen An PretInchir CodRegizor
10101 16 Blocks Actiune 2006 5.5 R1020
10103 Failure to launch Comedie 2006 5.5 R1021
10102 Man of the year Comedie 2006 5.5 R1019
Moartea domnului
10058 Lazarescu Drama 2005 3.5 R1017
10022 The Interpreter Drama 2005 5.5 R1015
10045 Meet the Fockers Comedie 2004 5.5 R1012
10077 Meet the parents Comedie 2003 5.5 R1011
10021 Cold Mountain Drama 2003 5.5 R1014
10023 Eyes Wide Shut Drama 1999 3.5 R1015
10011 Ronin Actiune 1998 3.5 R1011
10018 The Fifth Element Actiune 1997 3.5 R1013
10099 Leon Drama 1994 5.5 R1013
10055 The Firm Drama 1993 3.5 R1015
10013 RainMan Drama 1988 5.5 R1019

Să se obțină o listă cu comenzile clientului cu cod 100 ordonate de la cele mai


recente la cele mai vechi.

SELECT *
FROM COMENZI
WHERE CODCL = 100
ORDER BY datacom DESCENDING
TESTUL DE LA CURS
Se dă tabela FILME(CodFilm, Titlu, Gen, An, PretInchir, CodRegizor)

1. Să se afișeze lista filmelor mai vechi de anul 2000 pentru care nu se cunoaște
regizorul.
SELECT *
FROM FILME
WHERE AN<=2000 AND CODREGIZOR IS NULL

2. Să se afișeze titlul și anul apariției pentru filme din genul comedie, din anii 2010,
2012, 2014, ordonate după an descrescător.
SELECT titlu, an
FROM FILME
WHERE AN IN (2010, 2012, 2014) AND GEN="comedie"
ORDER BY an DESCENDING

3. Să se afișeze lista filmelor de genul dramă sau acțiune, al căror titlu conține
”batman”, ordonate după titlu.
SELECT *
FROM FILME
WHERE GEN IN ("actiune","drama") AND TITLU LIKE "*batman*"
ORDER BY titlu

(GEN = "actiune" OR GEN = ”drama”)

4. Corectați fraza SQL de mai jos


SELECT titlu, gen, an
FROM FILME
WHERE (an=2019 OR an=2020) AND gen = "drama"
Joncţiunea
Realizarea joncţiunii, a echi-joncţiunii sau a joncţiunii naturale se face în
clauza FROM. Cea mai utilizată este joncţiunea naturală, referită prin operatorul
INNER JOIN.
JONCŢIUNE=PRODUS CARTEZIAN + SELECŢIE
Aşa cum am văzut, clauza FROM defineşte produsul cartezian. Dacă după
acesta are loc selecţia se realizează în fapt joncţiunea. De aceea, clauza FROM
include şi condiţia de selecţie asupra produsului cartezian. Modalitatea generică de
scriere este:
SELECT T1.*, T2.*
FROM T1 INNER JOIN T2 ON T1.Atribut = T2.Atribut

unde T1 şi T2 sunt două tabele care îl au în comun pe Atribut.

Exemplu 11
Care sunt salariaţii care lucrează 40 de ore pe săptămână?
SELECT NumeSal, NrCentru
FROM SALARIATI INNER JOIN ORELUCRATE
ON SALARIATI.Marca = ORELUCRATE.Marca
WHERE OrePeSapt=40

Rezultat:
Numesal NrCentru
Albu Petre T001
Verdeţ Ion T002
George Crina T002
Fekete Iulian T004
Negru Iulia T004
Să se obțină o listă cu clienții care au comandat produsele cu cod 10 și 11 (nume,
localitate, data comenzii, cantitate), cu ordonare după dată și client.

SELECT nume, localit, datacom, cantitate


FROM COMENZI INNER JOIN CLIENTI ON
COMENZI.codclient = CLIENTI.cod
WHERE CODprodus = 10 or codprodus =11
ORDER BY datacom, nume

Să se obțină o listă cu clienții din județul Arad care au comandat cantități între
100 și 200 (nume, localitate, cod produs, cantitate) sortați alfabetic.

SELECT nume, localit, codprodus, cantitate


FROM COMENZI INNER JOIN CLIENTI ON
COMENZI.codclient = CLIENTI.cod
WHERE cantitate BETWEEN 100 AND 200 and judet = "AR"
ORDER BY nume

Să se obțină o listă cu comenzile la produse din depozitul 2 (nr comanda, data, cod
produs, cantitate, valoare comanda).
SELECT nrcom, datacom, codprodus,
cantitate, cantitate*pretlista
FROM COMENZI INNER JOIN PRODUSE ON
COMENZI.codprodus = PRODUSE.codprod
WHERE coddep = 2
Exemplu 12
Care sunt salariaţii din centrele din Timişoara care lucrează 40 de ore pe
săptămână?
SELECT NumeSal, SALARIATI.NrCentru, Oras
FROM (SALARIATI INNER JOIN ORELUCRATE
ON SALARIATI.Marca = ORELUCRATE.Marca)
INNER JOIN CENTRE ON SALARIATI.NrCentru = CENTRE.NrCentru
WHERE Oras = ”Timisoara” AND OrePeSapt = 40

Rezultat:
Nume NrCentru Oras
Albu Petre T001 Timisoara
Verdeţ Ion T002 Timisoara
George Crina T002 Timisoara
Exemplu 13
Care sunt personajele şi actorii din filmele apărute în 2003?
SELECT Titlu, Personaj, Nume
FROM (FILME INNER JOIN ROLURI ON FILME.CodFilm = ROLURI.CodFilm)
INNER JOIN ACTORI ON ROLURI.CodActor = ACTORI.CodActor
WHERE An = 2003

Rezultat:
Titlu Personaj Nume
Meet the parents Jack Byrnes Robert De Niro
Cold Mountain Sara Natalie Portman
Cold Mountain Ada Monroe Nicole Kidman

Să se obțină o listă cu clienții care au comandat produse din depozitul 2 în luna


noiembrie (nume, localitate, data comenzii, denumire produs, cantitate), cu
ordonare după produsul comandat.
SELECT nume, localit, datacom, denprod, cantitate
FROM (COMENZI INNER JOIN CLIENTI ON
COMENZI.codclient = CLIENTI.cod)
INNER JOIN PRODUSE ON
COMENZI.codprodus = PRODUSE.codprod
WHERE coddep = 2 AND MONTH(datacom) = 11
ORDER BY denprod
Să se obțină o listă cu clienții care au comandat produse cu stoc mai mic de 100 și
nu le-au fost livrate comenzile.
SELECT CLIENTI.*
FROM (COMENZI INNER JOIN CLIENTI ON
COMENZI.codCLIENT = CLIENTI.cod)
INNER JOIN COMENZI ON
COMENZI.codprodus = PRODUSE.codprod
WHERE stoc < 100 AND not livrat

Sub-consultări SQL

O facilitate deosebit de importantă a limbajului SQL o constituie posibilitatea


imbricării a două sau mai multe fraze SELECT, ceea ce permite formularea de
interogări cu mare grad de complexitate.
Pentru includerea unei fraze SELECT într-o altă frază SELECT se utilizează
operatorul IN.

Exemplu 1
Care sunt salariaţii care lucrează în acelaşi centru de închiriere cu
salariatul Nica Ioana?
SELECT *
FROM SALARIATI
WHERE NrCentru IN
(SELECT NrCentru
FROM SALARIATI
WHERE Nume=”Nica Ioana”)
Sub-consultarea
SELECT NrCentru
FROM SALARIATI
WHERE Nume=”Nica Ioana”
are ca rezultat o tabelă alcătuită dintr-o singură coloană (NrCentru) şi o
singură linie ce conţine valoarea atributului NrCentru pentru salariatul cu numele
Nica Ioana:
NrCentru
T001

Clauza WHERE NrCentru IN determină căutarea în tabela SALARIATI a


tuturor liniilor care au valoarea atributului NrCentru egală cu valoarea T001 găsită
prin sub-consultare.
Marca Nume Functie SalOra NrCentru
100 Albu Petre manager 50 T001
102 Nica Ioana vanzator 16 T001

Exemplu 2
Care sunt actorii care au jucat în aceleaşi filme cu Jean Reno?
SELECT NumeActor
FROM ROLURI INNER JOIN ACTORI ON
ROLURI.CodActor = ACTORI.CodActor
WHERE CodFilm IN
(SELECT CodFilm
FROM ROLURI INNER JOIN ACTORI ON
ROLURI.CodActor = ACTORI.CodActor
WHERE Nume=”Jean Reno”)
Rezolvare:
Nume
Robert DeNiro
Jean Reno
Natalie Portman
Gary Oldman
Rezolvarea exemplului de mai sus a presupus realizarea de joncţiuni în cadrul
sub-consultării. O altă variantă de rezolvare este şi:
SELECT Nume
FROM ACTORI
WHERE CodActor IN
(SELECT CodActor
FROM ROLURI
WHERE CodFilm IN
(SELECT CodFilm FROM ROLURI
WHERE CodActor IN
(SELECT CodActor FROM ACTORI
WHERE Nume=”Jean Reno”)))

Am ilustrat modul în care pot fi înlănţuite patru fraze SELECT. Această soluţie
"merge" în ACCESS, nu şi în alte SGBD-uri, precum Visual FoxPro, unde este posibil
doar un nivel de sub-consultare.
Se poate reţine, ca regulă generală, că aproape orice consultare poate fi
redactată în mai multe moduri, în funcţie de experienţa şi imaginaţia celui care
o formulează.

Funcţii agregate: COUNT, SUM, AVG, MAX, MIN

Funcţiile predefinite sunt extreme de utile utilizatorilor în realizarea de calcule


rezumative asupra datelor, precum suma, medie, minim, maxim sau numărare.
Rezultatul unei fraze SELECT care conţine o funcţie de acest tip este o tabelă
cu o singură linie.

Funcţia COUNT numără valorile unei coloane.


Altfel spus, numără, într-o relaţie, câte valori diferite de <null> sunt pe
coloana specificată.
Exemplu 1
Câţi salariaţi are firma?
SELECT COUNT(Marca) AS Nr_Salariati
FROM SALARIATI

Rezultat:
Nr_Salariati
7

În funcţia COUNT se poate utiliza ca argument, în locul numelui unei coloane,


semnul *; de asemenea, poate apare clauza WHERE - se vor număra liniile din
tabelă care verifică condiţia specificată.
Exemplu 2
Câte filme mai vechi de 2000 există în BD?
SELECT COUNT() AS Cate_Filme
FROM FILME
WHERE An < 2000

Rezultat:
Cate_Filme
6

Câte comenzi au fost în ziua de 11 noiembrie?

SELECT COUNT(*) AS NrComenzi


FROM COMENZI
WHERE datacom = #11/11/2020#
Câte comenzi au fost pentru produse din depozitul 2?

SELECT COUNT(nrcom) AS NrComenziDep2


FROM COMENZI INNER JOIN PRODUSE ON
COMENZI.codprodus = PRODUSE.codprod
WHERE coddep = 2

Funcţia SUM calculează suma valorilor unei coloane.

Exemplu 3
Care este numărul total de ore lucrate pe săptămână la toate
centrele?
SELECT SUM(OrePeSapt) AS Total_Ore
FROM ORELUCRATE
Rezultat:
Total_Ore
270
Exemplu 4
Care este numărul total de ore lucrate săptămânal în centrele din
Timişoara?
SELECT SUM (OrePeSapt) AS Total_Ore_TM
FROM ORELUCRATE INNER JOIN CENTRE
ON ORELUCRATE.NrCentru = CENTRE.NrCentru
WHERE Oras = “Timisoara”
Rezultat:
Total_Ore_TM
190

Cât este total valoare facturi?

SELECT SUM(ValcuTVA) AS TotalValFact


FROM FACTURI
Cât s-a vândut în total în prima săptămână din noiembrie?
SELECT SUM(ValcuTVA) AS TotalValFact
FROM FACTURI
WHERE datafact BETWEEN #11/1/2020# AND #11/7/2020#
Cât s-a vândut în total clienților din Timișoara?
SELECT SUM(ValcuTVA) AS TotalValFactTM
FROM FACTURI INNER JOIN CLIENTI ON FACTURI.codcl =
CLIENTI.cod
WHERE LOCALIT = ”Timisoara”
Funcţiile MAX şi MIN determină valorile maxime, respectiv
minime ale unei coloane în cadrul unei tabele.
Exemplu 5
Care este numărul maxim de ore lucrate săptămânal?
SELECT MAX(NrOreSapt) AS MaxOre
FROM ORELUCRATE
Rezultat:
MaxOre
40

Care sunt cea mai mică și cea mai mare cantitate comandată?

SELECT MIN(Cantitate) AS CantMin, MAX(Cantitate) AS CantMax


FROM COMENZI

Care este valoarea cea mai mare a facturii clienților din județul Arad?

SELECT MAX(valcutva) AS ValMaxArad


FROM FACTURI INNER JOIN CLIENTI ON
FACTURI.codcl = CLIENTI.cod
WHERE judet = "ar"
Exemplu 6
Care este filmul cel mai vechi din baza noastra de date?
SELECT Titlu, An
FROM FILME
WHERE An IN (SELECT MIN(An) FROM FILME)

Se execută mai întâi SELECT din paranteză și dă valoarea 1988, apoi se aleg
titlu și an din tabela FILME:

Titlu An
RainMan 1988

Care este clientul care are valoarea cea mai mare a facturii?

SELECT nume
FROM CLIENTI
WHERE cod IN
(SELECT codcl FROM FACTURI WHERE
VALCUTVA IN (SELECT MAX(valcutva) FROM FACTURI)

Opţiuni de grupare a liniilor

SQL permite utilizarea clauzei GROUP BY pentru a forma grupuri de


înregistrări dintr-o tabelă, pe baza valorilor comune ale unei coloane.
Prin asocierea unei clauze HAVING la o clauză GROUP BY este posibilă
selectarea dintre grupurile de înregistrări a celor care îndeplinesc o condiţie
specificată.
 Observaţie:
Clauza WHERE poate fi utilizată doar pentru a selecta înregistrări, ea nu poate
lucra cu grupuri de înregistrări.

Rezultatul unei fraze SELECT ce conţine clauza GROUP BY este o tabelă care
va fi obţinută prin regruparea tuturor liniilor din tabelele enumerate în FROM, care
prezintă o aceeaşi valoare pentru o coloană.
Exemplu 1
Care este numărul de filme disponibile pentru fiecare gen?
SELECT Gen, COUNT(CodFilm) As NrFilme
FROM FILME
GROUP BY Gen
Rezultat:
Gen NrFilme
Comedie 4
Drama 7
Actiune 3

În acest caz tabela-rezultat va avea un număr de linii egal cu numărul de


genuri de filme definite în tabela FILME. Pentru toate gen se vor număra filmele.
Succesiunea paşilor este următoarea:
Pasul 1. Se ordonează liniile tabelei FILME după valorile atributului Gen:
CodFilm Titlu Gen An PretInchir CodRegizor
10101 16 Blocks Actiune 2006 5.5 R1020
10011 Ronin Actiune 1998 3.5 R1011
10018 The Fifth Element Actiune 1997 3.5 R1013
10103 Failure to launch Comedie 2006 5.5 R1021
10102 Man of the year Comedie 2006 5.5 R1019
10045 Meet the Fockers Comedie 2004 5.5 R1012
10077 Meet the parents Comedie 2003 5.5 R1011
Moartea domnului
10058 Lazarescu Drama 2005 3.5 R1017
10022 The Interpreter Drama 2005 5.5 R1015
10021 Cold Mountain Drama 2003 5.5 R1014
10023 Eyes Wide Shut Drama 1999 3.5 R1015
10099 Leon Drama 1994 5.5 R1013
10055 The Firm Drama 1993 3.5 R1015
10013 RainMan Drama 1988 5.5 R1019
Pasul 2. Se formează câte un grup pentru fiecare valoare distinctă a
atributului Gen:
CodFilm Titlu Gen An PretInchir CodRegizor
10101 16 Blocks Actiune 2006 5.5 R1020
10011 Ronin Actiune 1998 3.5 R1011
10018 The Fifth Element Actiune 1997 3.5 R1013
10103 Failure to launch Comedie 2006 5.5 R1021
10102 Man of the year Comedie 2006 5.5 R1019
10045 Meet the Fockers Comedie 2004 5.5 R1012
10077 Meet the parents Comedie 2003 5.5 R1011
10058 Moartea domnului
Lazarescu Drama 2005 3.5 R1017
10022 The Interpreter Drama 2005 5.5 R1015
10021 Cold Mountain Drama 2003 5.5 R1014
10023 Eyes Wide Shut Drama 1999 3.5 R1015
10099 Leon Drama 1994 5.5 R1013
10055 The Firm Drama 1993 3.5 R1015
10013 RainMan Drama 1988 5.5 R1019

Pasul 3. Pentru fiecare din cele trei grupuri se numără liniile.


Tabela-rezultat final va avea trei linii:
Gen NrFilme
Comedie 4
Drama 7
Actiune 3

Cât este total valoare facturi pentru fiecare client?

SELECT CodCl, SUM(ValcuTVA) AS TotalValFact


FROM FACTURI
GROUP BY Codcl

codcl TotalValfact
100 2754
101 3143
..... ..........

Cât este total valoare facturi pentru fiecare zi?

SELECT Datafact, SUM(ValcuTVA) AS TotalValFact


FROM FACTURI
GROUP BY Datafact
Cât s-a vândut în total clienților din fiecare județ?
SELECT Judet, SUM(ValcuTVA) AS TotalValFact
FROM FACTURI INNER JOIN CLIENTI ON
CLIENTI.Cod = FACTURI.codCLIENT
GROUP BY JUDET

Exemplu 2
Care este numărul de filme pentru fiecare regizor ?
SELECT NumeRegizor, COUNT(CodFilm) AS NrFilme
FROM FILME INNER JOIN REGIZORI ON
FILME.CodRegizor=REGIZORI.CodRegizor
GROUP BY FILME.CodRegizor
ORDER BY NumeRegizor
Rezultat:
NumeRegizor NrFilme
Anthony Minghella 1
Barry Levinson 2
Cristi Puiu 1
Jay Roach 1
John Frankenheimer 2
Luc Besson 2
Richard Donner 1
Sydney Pollack 3
Tom Dey 1
Clauza HAVING permite introducerea unor restricţii asupra grupurilor de
înregistrări, astfel că în tabela-rezultat sunt incluse doar grupurile care satisfac
condiţia specificată.
Clauza HAVING se foloseşte doar împreună cu o clauză GROUP BY (Este ca
o clauză WHERE aplicată grupurilor).
Exemplu 3
Care sunt regizorii care au mai mult de 2 filme în baza noastră de
date?
SELECT NumeRegizor, COUNT(CodFilm) AS NrFilme
FROM FILME INNER JOIN REGIZORI ON
FILME.CodRegizor=REGIZORI.CodRegizor
GROUP BY FILME.CodRegizor
ORDER BY NumeRegizor
HAVING COUNT(CodFilm)>=2
Rezultat:
NumeRegizor NrFilme
Barry Levinson 2
John Frankenheimer 2
Luc Besson 2
Sydney Pollack 3

La execuţia acestei fraze, se parcurg cei trei paşi prezentaţi la exemplul 1,


apoi, din cele nouă tupluri obţinute prin grupare, sunt extrase numai cele care
îndeplinesc condiţia COUNT(CodFilm)>=2.

Care au fost zilele în care am avut mai mult de 5 comenzi?

SELECT datacom, COUNT(*) AS NrComenzi


FROM COMENZI
GROUP BY datacom
HAVING COUNT(*) >= 5
TESTUL DE LA CURS

1. Să se indice numărul filmelor de comedie mai vechi de anul 2000.

SELECT COUNT(*)
FROM FILME
WHERE GEN=”COMEDIE” AND AN<2000

2. Să se obțină lista filmelor din ultimul deceniu al secolului 20, în care


apare personajul Batman, sortate descrescător după anul apariției.
SELECT FILME.CODFILM, TITLU, AN
FROM FILME INNER JOIN ROLURI ON
FILME.CODFILM=ROLURI.CODFILM
WHERE PERSONAJ = “BATMAN” AND AN BETWEEN 1990 AND 1999
SORT BY AN DESCENDING

3. Ce afișează următoarea interogare?


SELECT NUME
FROM ACTORI INNER JOIN FILME
ON FILME.CODACTOR = ACTORI.CODACTOR
WHERE GEN=”ACTIUNE” OR GEN = “COMEDIE”
a) lista actorilor care joacă în filme
b) lista filmelor de acțiune și de comedie
c) lista actorilor care apar în filme de actiune și de comedie
d) niciuna din cele de mai sus

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