Sunteți pe pagina 1din 19

Interogri la nivel de grup (de agregare / sintetizatoare) Multe dintre cererile de informaii nu necesit nivelul de detaliere furnizat de interogrile

SQL prezentate pn acum. De exemplu, urmtoarele cerine presupun determinarea unei singure valori sau a unui numr mic de valori care sintetizeaz coninutul bazei de date. Care este totalul cotelor tuturor agenilor de vnzri? Care este cea mai mic, respectiv cea mai mare cot ? Ci ageni de vnzri si-au depit cota ? Care este media valorii comenzilor ? Care este media valorii comenzilor pentru fiecare birou de vnzri n parte? C ageni de vnzri lucreaz la fiecare birou de vnzri n parte ? SQL poate rspunde la aceste cereri prin utilizarea unor funcii de grup i prin utilizarea clauzelor GROUP BY i HAVING n instruciunea SELECT. Funcii de grup SQL ne permite s sintetizm datele din baza de date prin utilizarea unor funcii de grup asupra coloanelor. O funcie de grup primete ca argument o ntreag coloan i furnizeaz ca rezultat o singur valoare, care sintetizeaz datele din coloana respectiv. De exemplu, funcia AVG( ) primete ca parametru datele dintr-o coloan i returneaz media lor aritmetic. Care este cota medie de vnzri i media vnzrilor pentru agenii de vnzri ?

Figura 5.17 ne arat grafic cum sunt obinute rezultatele interogrii. Prima funcie de grup primete ca parametru valorile din coloana QUOTA i calculeaz media lor aritmetic ; cea de-a doua funcie calculeaz media aritmetic a valorilor din coloana SALES. Interogarea produce o singur linie n rezultatul interogrii, linie care sintetizeaz datele din tabela SALESREPS.

Figura 5.17 Interogare sintetizatoare SQL ofer ase funcii de grup: SUM() calculeaz totalul valorilor dintr-o coloan. AVG() calculeaz media aritmetic a valorilor dintr-o coloan. MIN() determin cea mai mic dintre valorile unei coloane. MAX() determin cea mai mic dintre valorile unei coloane. COUNT() determin numrul valorilor dintr-o coloan. COUNT(*) determin numrul liniilor din rezultatul interogrii. Argumentul unei funcii de grup poate fi numele unei coloane, ca n exemplul precedent, sau o expresie SQL. Care este procentul mediu de vnzri al agenilor?

Pentru a procesa aceast interogare, SQL construiete o coloan temporar care conine valoarea expresiei (100 * (SALES/QUOTA)) pentru fiecare linie din tabela SALESREPS i apoi calculeaz media aritmetic a valorilor acestei coloane.

Determinarea totalului unei coloane (SUM) Funcia de grup SUM( ) determin suma valorilor dintr-o coloan. Datele din coloana respectiv trebuie s fie de tip numeric (ntreg, real zecimal, real in virgul mobil sau money). Rezultatul funciei SUM( ) este de acelai tip cu datele din coloana respectiv dar rezultatul poate avea precizie mai mare. n continuare sunt prezentate cteva exemple care utilizeaz funcia SUM( ). Care este totalul cotelor i al vnzrilor tuturor agenilor de vnzri?

Care este totalul comenzilor primite de Bill Adams?

Determinarea mediei aritmetice (AVG) Funcia de grup AVG( ) determin media aritmetic a valorilor dintr-o coloan. Ca i n cazul funciei SUM( ), datele din coloana respectiv trebuie s fie de tip numeric. Tipul de dat al rezultatului poate s difere de cel al valorilor din coloana respectiv. De exemplu, dac aplicm funcia AVG( ) unei coloane de tip ntreg, rezultatul poate fi de tip real zecimal sau real n virgul mobil, n funcie de SGBD-ul pe care lucrm. n continuare sunt prezentate cteva exemple care utilizeaz funcia AVG( ). S se determine preul mediu al produselor realizate de ACI.

S se determine valoarea medie a comenzilor fcute de ACME Mfg. (clientul cu numrul 2103)

Determinarea valorilor minime i maxime (MIN i MAX) Funciile de grup MIN() i MAX() determin cea mai mic, respectiv cea mai mare, dintre valorile unei coloane. Datele din coloana respectiv pot fi de tip numeric, ir de caractere sau date/time. Rezultatul va avea exact acelai tip de dat cu al valorilor din coloana respectiv. Mai jos sunt prezentate cteva exemple care utilizeaz aceste funcii de grup. Care sunt cea mai mic i cea mai mare dintre cotele agenilor de vnzri?

Care este cea mai veche comand existent n baza de date?

Care este cel mai bun procent de vnzri al unui agent?

Cnd sunt utilizate funciile de grup MIN( ) i MAX( ), numerele sunt comparate n ordine algebric, irurile de caractere n ordine lexicografic, datele calendaristice n ordine cronologic iar duratele de timp pe baza lungimii acestora. Numrarea valorilor (COUNT) Funcia de grup COUNT( ) numr valorile dintr-o coloan. Datele din coloana respectiv pot avea orice tip de dat. Funcia COUNT( ) returneaz un ntreg. Mai jos sunt prezentate cteva exemple de interogri n care este utilizat aceast funcie. S se determine numrul clienilor.

Care este numrul agenilor de vnzri care i-au depit cota ?

Cte comenzi au valoarea mai mare de $25.000 ?

Funcia COUNT( ) ignor valorile datelor din coloana transmis ca parametru; ea pur i simplu numr valorile din aceast coloan. Ca urmare, nu conteaz ce coloan i specificm ca argument. Exemplul precedent poate fi scris aadar i n modul urmtor:

De fapt nu este eficient s gndim interogarea sub forma "numr cte valori de comezi " sau "numr cte numere de comezi " ; este mai simplu s gndim "numr cte comenzi ". Din acest motiv SQL suport o funcie de grup special , COUNT( * ), care numr liniile i nu valorile datelor. n continuare este reformulat interogarea anterioar utiliznd funcia COUNT (*) .

Dac ne gndim la funcia COUNT( * ) ca avnd semnificaia numr liniile, interogarea devine mai uor de citit. n practic funcia COUNT( * ) este aproape ntotdeauna utilizat n locul funciei COUNT( ) pentru a numra linii. Valorile nule i funciile de grup Funciile de grup, SUM(), AVG(), MIN(), MAX(), i COUNT() primesc ca argument valorile unei coloane i furnizeaz ca rezultat o singur valoare. Ce se ntmpl dac una sau mai multe dintre valorile coloanei respective sunt NULL? Standardul ANSI/ISO SQL precizeaz c valorile NULL sunt ignorate de funciile de grup.

Urmtoarea interogare ne arat cum funcia COUNT() ignor valorile NULL dintr-o coloan.

Tabela SALESREPS conine zece linii, aadar COUNT( * ) returneaz zece. Coloana SALES conine zece valori NOT NULL, aadar COUNT(SALES) returneaz, de asemenea, valoarea zece. Coloana QUOTA are valoarea NULL pentru cel mai nou agent de vnzri; funcia COUNT(QUOTA) ignor aceast valoare NULL i returneaz valoarea nou. Din cauza acestei anomalii, funcia count( * ) este aproape ntotdeauna utilizat n locul funciei count( ), cu excepia situaiilor n care dorim s specificm, pentru o anumit coloan, excluderea valorilor NULL din numrul total al valorilor. Ignorarea valorilor NULL are un impact mai mic n cazul funciilor MIN( ) i MAX( ) totui poate cauza unele probleme n cazul funciilor SUM( ) i AVG( ). S considerm urmtorul exemplu:

Ne-am atepta ca cele dou expresii - (SUM(SALES) SUM(QUOTA)) i SUM(SALES-QUOTA) din lista de selecie s produc acelai rezultat dar exemplul ne arat c nu este aa. Motivul este faptul c n coloana QUOTA exist o valoare NULL. Expresia SUM(SALES) nsumeaz totalul vnzrilor pentru toi cei zece ageni de vnzri n timp ce expresia SUM(QUOTA) nsumeaz numai nou valori ale cotelor. Expresia SUM(SALES) SUM(QUOTA) calculeaz diferena dintre cele dou totaluri. Totui, funcia de grup SUM(SALES-QUOTA) are argumente valori nenule doar pentru nou din cei zece ageni; n linia cu o valoare NULL pentru cot, diferena furnizeaz valoarea NULL, care este ignorat de funcia SUM( ). Astfel, vnzrile pentru agentul fr cot, care sunt incluse n calculul anterior, sunt excluse din acest calcul. Aadar, cnd apar valori NULL, cele dou expresii nu calculeaz exact acelai lucru. Standardul ANSI/ISO specific reguli precise pentru tratarea valorilor nule n cazul funciilor de grup: Dac o valoare dintr-o coloan este NULL, aceasta este ignorat de funciile de grup.

Dac o coloan nu conine date (aadar coloana este goal) atunci funciile de grup SUM( ), AVG( ), MIN( ) i MAX( ) returneaz valoarea NULL; funcia COUNT( ) returneaz valoarea zero. Funcia COUNT( * ) numr liniile i nu depinde de prezena sau absena valorilor NULL ntr-o coloan. Dac nu exist linii, returneaz valoarea zero. Eliminarea liniilor duplicat (DISTINCT) Reamintim faptul c putem aduga cuvntul cheie DISTINCT la nceputul listei de selecie pentru a elimina liniile duplicat din rezultatul interogrii. Putem, de asemenea, s eliminm valorile duplicat dintr-o coloan nainte de a aplica funcii de grup asupra acesteia. Pentru a elimina valorile duplicat includem cuvntul cheie DISTINCT nainte de argumentul funciei de grup, imediat dup paranteza deschis. n continuare sunt prezentate dou exemple care ilustreaz cum sunt eliminate valorile duplicat n cazul funciilor de grup. Cte titluri distincte sunt deinute de agenii de vnzri?

Cte birouri de vnzri au ageni care si-au depit cota?

Gruparea nregistrrilor (Clauza GROUP BY ) Interogrile totalizatoare prezentate pn acum seamn cu totalurile de la sfritul unui raport. Ele condenseaz toate datele detaliate din raport ntr-o singur linie. Uneori ns, n rapoartele tiprite avem nevoie i de subtotaluri. Clauza GROUP BY ne ofer posibilitatea de a realiza acest lucru. Rolul clauzei GROUP BY este cel mai uor de neles prin exemple. S considerm urmtoarele dou interogri: Care este media valorilor comenzilor?

Care este media valorilor comenzilor realizate de fiecare agent de vnzri?

Prima interogare este o simpl interogare totalizatoare, ca n exemplele anterioare. Cea de-a doua, produce cteva linii totalizatoare cte una pentru fiecare grup, nsumnd valorile comenzilor primite de un agent de vnzare. Figura 5.18 ne arat cum lucreaz cea de-a doua interogare.

Figura 5.18 Gruparea nregistrrilor Conceptual, SQL proceseaz interogarea astfel: 1. SQL mparte comenzile n grupuri de comenzi, cte un grup pentru fiecare agent de vnzri. n interiorul unui grup, toate comenzile au aceeai valoare a coloanei REP. 2. Pentru fiecare grup, SQL calculeaz media valorilor coloanei AMOUNT i genereaz o singur linie n rezultatul interogrii ; linia conine valoarea coloanei REP pentru grupul respectiv i media aritmetic a valorilor comenzilor Care este intervalul n care sunt cuprinse cotele asignate pentru fiecare birou de vnzri?

Ci ageni de vnzri lucreaz la fiecare birou n parte?

Ci clieni diferii sunt servii de fiecare agent de vnzri n parte?

10

Exist o legtur strns ntre funciile de grup i clauza GROUP BY. Reamintim c o funcie de grup primete ca argument valorile dintr-o coloan i produce ca rezultat o singur linie. Cnd este prezent clauza GROUP BY, SQL grupeaz nregistrrile i aplic funcia de grup fiecruia dintre grupuri n parte, producnd n rezultat cte o singur linie pentru un grup. Gruparea dup mai multe coloane SQL poate grupa rezultatele interogrii pe baza coninutului a dou sau mai multe coloane. De exemplu, s presupunem c dorim s grupm comenzile dup agenii de vnzri i dup clieni. Urmtoarea interogare grupeaz datele pe baza ambelor criterii: S se calculeze totalul valorii comenzilor pentru fiecare agent de vnzri i pentru fiecare client.

11

Chiar i n cazul gruprii dup mai multe coloane, SQL furnizeaz un singur nivel de grupare. Interogarea produce cte o linie separat pentru fiecare pereche agent de vnzri/client. Este imposibil n SQL s crem grupuri i subgrupuri cu dou nivele de subtotaluri. Tot ce putem face este s ordonm rezultatele interogrii. S se calculeze totalul comenzilor pentru fiecare client i pentru fiecare agent de vnzri, ordonate dup client i, pentru fiecare client n parte, ordonate dup agenii de vnzri.

12

Menionm, de asemenea, c este imposibil s obinem att rezultate detaliate ct i rezultate totalizatoare ntr-o interogare SQL. Pentru a obine rezultate detaliate, cu subtotaluri, sau subtotaluri pe mai multe nivele, este nevoie s utilizm SQL programatic. Restricii asupra gruprii nregistrrilor Gruparea nregistrrilor este supus anumitor restricii. Coloanele dup care se face gruparea trebuie s fie coloane ale tabelelor specificate n clauza FROM. Nu putem face gruparea pe baza unor valori calculate. Exist, de asemenea, restricii n ce privete lista de selecie: toate elementele care apar n lista de selecie trebuie s aib aceeai valoare pentru toate liniile din grup. Aceasta nseamn c lista de selecie poate conine: O constant O funcie de grup O coloan de grupare, care are prin definiie aceeai valoare pentru toate liniile din grup Orice expresie care conine combinaii ale elementelor de mai sus. n practic, o interogare cu gruparea nregistrrilor va include ntotdeauna n lista de selecie att o coloan de grupare ct i o funcie de grup. Dac n lista de selecie nu apare nici o funcie de grup atunci interogarea poate fi exprimat mai simplu utiliznd clauza SELECT DISTINCT, fr GROUP BY. Reciproc, dac nu includem n lista de selecie o coloan de grupare, nu vom putea preciza crui grup i corespunde o anumit linie din rezultatul interogrii. O alt limitare const n faptul c SQL ignor informaiile referitoare la cheile primare i la cele strine cnd analizeaz corectitudinea gruprii nregistrrilor. S se calculeze totalul comenzilor pentru fiecare agent de vnzri.

13

Avnd n vedere natura datelor, interogarea pare corect deoarece gruparea dup numrul agentului de vnzri este de fapt aceeai cu gruparea dup numrul i apoi dup numele acestuia. Mai exact, EMPL_NUM este cheie primar n tabela SALESREPS aadar coloana NAME va avea o singur valoare pentru fiecare grup. Cu toate acestea, SQL semnaleaz o eroare deoarece coloana NAME nu este specificat explicit n coloanele de grupare. Pentru a elimina eroarea trebuie s includem coloana NAME ca pe a doua coloan de grupare. S se calculeze totalul comenzilor pentru fiecare agent de vnzri.

Bineneles, dac numrul agentului de vnzri nu este necesar n rezultatul interogrii, l putem elimina din lista de selecie. S se calculeze totalul comenzilor pentru fiecare agent de vnzri.

14

Valori NULL n coloanele de grupare Prezena unor valori null n coloanele dup care se face gruparea nregistrrilor ridic anumite probleme. Dac valoarea coloanei este necunoscut, crui grup i va fi asociat nregistrarea ? n clauza WHERE, cnd sunt comparate dou valori NULL distincte, rezultatul este NULL (nu TRUE); aadar, dou valori NULL distincte nu sunt considerate egale. Aplicarea acestei reguli n cazul clauzei GROUP BY, ar face ca fiecare dintre liniile care au valoarea NULL n coloana de grupare s fie plasate n cte un grup. Aceast regul se dovedete a fi prea dificil. Standardul ANSI/ISO SQL precizeaz c n cazul n care este prezent clauza GROUP BY, valorile NULL din coloana de grupare sunt considerate egale. Astfel, dac dou linii au valoarea NULL ntr-o coloan de grupare i valori nenule identice n celelalte coloane de grupare, ele vor fi grupate mpreun. Urmtorul exemplu de interogare se refer la tabela din Figura 5.19 i ilustreaz cum trateaz SQL valorile NULL n cazul clauzei GROUP BY.

15

Figura 5.19 Tabela PEOPLE SELECT HAIR, EYES, COUNT(*) FROM PEOPLE GROUP BY HAIR, EYES HAIR ------Brown NULL NULL Brown Brown Blonde EYES --------Blue Blue NULL NULL Brown Blue COUNT(*) -------------1 2 2 4 1 2

Dei modul de tratare a valorilor NULL n cazul clauzei GROUP BY este clar specificat n standardul ANSI/ISO, el nu este implementat nc de toate SGBD-urile. Se recomand realizarea, n prealabil a unor mici aplicaii de testare a comportamentului specific al SGBD-ului respectiv. Selecia grupurilor de nregistrri (Clauza HAVING) Aa cum clauza WHERE este utilizat pentru a selecta, individual, liniile care intervin ntr-o interogare, clauza HAVING poate fi utilizat pentru a selecta grupuri de linii. Clauza HAVING const din cuvntul rezervat HAVING urmat de o condiie de selecie pentru grupurile de linii. S considerm urmtorul exemplu : Care este media valorii comenzilor pentru acei ageni de vnzri ale cror comenzi nsumeaz mai mult de $30.000? 16

Figura 5.20 ne arat grafic cum proceseaz SQL aceast interogare. Mai nti, clauza GROUP BY grupeaz comenzile dup id-urile agenilor de vnzri ; apoi, clauza HAVING elimin orice grup pentru care totalul comenzilor nu depete $30.000. n final, clauza SELECT calculeaz media aritmetic a comenzilor pentru fiecare din grupurile rmase i genereaz rezultatul interogrii. Condiiile de selecie pe care le putem include n clauza HAVING sunt aceleai ca n cazul clauzei WHERE.

Figura 5.20 Procesarea seleciei grupurilor de nregistrri

17

Pentru fiecare birou cu doi sau mai muli angajai, s se calculeze cota total i totalul vnzrilor pentru toi agenii de vnzri care lucreaz n biroul respectiv.

S se afieze preul, cantitatea aflat n stoc i cantitatea total comandat din fiecare produs pentru care cantitatea total comandat este cu 75% mai mare dect cantitatea aflat n stoc.

Pentru a procesa aceast interogare, SQL parcurge urmtorii pai : 1. Efectueaz joinul tabelelor ORDERS i PRODUCTS pentru a afla descrierea, preul i cantitatea din stoc pentru fiecare produs comandat. 2. Grupeaz liniile rezultate dup id-ul productorului i al produsului. 3. Elimin grupurile n care cantitatea comandat (suma coloanei QTY pentru toate comenzile din grup) este mai mic dect 75% din cantitatea aflat n stoc. 4. Calculeaz cantitatea total pentru fiecare grup. 18

5. Genereaz cte o linie totalizatoare n rezultatul interogrii, pentru fiecare grup. 6. Ordoneaz liniile din rezultat n ordinea descresctoare a cantitii. Aa cum am precizat anterior, coloanele DESCRIPTION, PRICE i QTY_ON_HAND trebuie specificate ca i coloane de grupare dor pentru c apar n lista de selecie. Ele nu contribuie de fapt cu nimic la gruparea nregistrrilor, deoarece MFR_ID i PRODUCT_ID identific o singur linie din tabela PRODUCTS. Restricii asupra condiiei de selecie a grupurilor de nregistrri Clauza HAVING este utilizat pentru a exclude grupuri de linii din rezultatul interogrii, aadar condiia de selecie pe care o conine trebuie s fie una care se aplic grupului ca ntreg mai degrab dect liniilor individuale. Aceasta nseamn un element din condiia de selecie a clauzei HAVING poate fi: O constant O funcie de grup O coloan de grupare, care are prin definiie aceeai valoare pentru toate liniile din grup Orice expresie care conine combinaii ale elementelor de mai sus. n practic, condiia de selecie din clauza HAVING va include cel puin o funcie de grup. Dac nu, atunci condiia de selecie poate fi mutat n clauza WHERE i aplicat liniilor individuale. Valorile NULL i condiia de selecie din clauza HAVING Ca i condiia de selecie din clauza WHERE, condiia de selecie din clauza HAVING poate produce unul dintre urmtoarele trei rezultate: TRUE, FALSE sau NULL. Numai grupurile pentru care condiia de selecie este TRUE vor contribui la obinerea rezultatelor interogrii. Anomaliile care pot aprea n legtur cu valorile NULL sunt aceleai ca n cazul clauzei WHERE.

19