You are on page 1of 42

Universitatea Al.I.

Cuza Iai
Facultatea de Economie i Administrarea Afacerilor
Departamentul de Contabilitate, Informatic economic i
Statistic

SQL (4)
Marin
Fotache

Predicate & NULL,


jonciuni externe,
structuri CASE

Liniile tabelei CLIENI

Valori NULL ale


atributului Telefon

NULL - o prim problem


SELECT * FRO M clienti
W H ERE Telefon IN ('0232212121', N U LL)

NULL a doua problem


Care dintre clieni au adresa specificat /
cunoscut ?

SELECT * FRO M clienti


W H ERE Adresa N O T IN (N U LL)

Extragerea valorilor NULL


Pentru care dintre clieni nu se cunoate
adresa ?
SELECT * FRO M clienti
W H ERE Adresa IS N U LL

IS NULL corect
= NULL incorect !!!
SELECT *
FRO M CLIEN TI
W H ERE Adresa = N U LL

Ordonri i NULL-iti
S se ordoneze clienii dup numerele de
telefon, valorile NULL fiind plasate la nceput

SELECT * FRO M clienti


O RD ER BY Telefon N U LLS FIRST

Dou tabele noi: PERSONAL

i SPORURI

Crearea celor dou tabele


CREATE TABLE personal (
Marca NUMERIC(5) NOT NULL CONSTRAINT pk_personal2 PRIMARY KEY,
NumePren VARCHAR(40) NOT NULL,
DataNast DATE,
Compart VARCHAR(20),
MarcaSef NUMERIC(5) CONSTRAINT fk_personal2 REFERENCES personal
(marca),
SalTarifar NUMERIC(12,2)
);
CREATE TABLE sporuri (
An NUMERIC(4) NOT NULL,
Luna NUMERIC(2) NOT NULL,
Marca NUMERIC(5) NOT NULL
CONSTRAINT fk_sporuri_personal REFERENCES personal (marca),
SporVechime NUMERIC(12,2),
SporNoapte NUMERIC(12,2),
SporCD NUMERIC(12,2),
AlteSpor NUMERIC(12,2),
CONSTRAINT pk_sporuri PRIMARY KEY (an,luna,marca) ) ;

Popularea celor dou tabele (1)


INSERT INTO personal VALUES (1, 'ANGAJAT 1', DATE'1962-07-01',
'DIRECTIUNE', NULL, 1600) ;
INSERT INTO personal VALUES (2, 'ANGAJAT 2', DATE'1977-10-11', 'FINANCIAR', 1,
1450) ;
INSERT INTO personal VALUES (3, 'ANGAJAT 3', DATE'1962-08-02', 'MARKETING',
1, 1450) ;
INSERT INTO personal VALUES (4, 'ANGAJAT 4', NULL, 'FINANCIAR', 2, 1380) ;
INSERT INTO personal VALUES (5, 'ANGAJAT 5', DATE'1965-04-30', 'FINANCIAR', 2,
1420) ;
INSERT INTO personal VALUES (6, 'ANGAJAT 6', DATE'1965-11-09', 'FINANCIAR', 5,
1350) ;
INSERT INTO personal VALUES (7, 'ANGAJAT 7', NULL, 'FINANCIAR', 5, 1280) ;
INSERT INTO personal VALUES (8, 'ANGAJAT 8', DATE'1960-12-31', 'MARKETING',
3, 1290) ;
INSERT INTO personal VALUES (9, 'ANGAJAT 9', DATE'1976-02-28', 'MARKETING',
3, 1410) ;
INSERT INTO personal VALUES (10, 'ANGAJAT 10', DATE'1972-01-29',
'RESURSE UMANE', 1, 1370) ;

Popularea celor dou tabele (2)


INSERT INTO sporuri VALUES (2011, 5, 2, 80, 45, 0, 70) ;
INSERT INTO sporuri VALUES (2011, 5, 3, 145, 0, 0, 0) ;
INSERT INTO sporuri VALUES (2011, 5, 10, 137, 0, 0, 430) ;
INSERT INTO sporuri VALUES (2011, 6, 1, 160, 0, 0, 0) ;
INSERT INTO sporuri VALUES (2011, 6, 2, 80, 0, 0, 150) ;
INSERT INTO sporuri VALUES (2011, 6, 4, 50, 15, 88, 120) ;
INSERT INTO sporuri VALUES (2011, 6, 5, 130, 15, 0, 20) ;
INSERT INTO sporuri VALUES (2011, 6, 10, 200, 12, 0, 6) ;
INSERT INTO sporuri VALUES (2011, 7, 1, 160, 0, NULL, NULL) ;
INSERT INTO sporuri VALUES (2011, 7, 2, 80, 0, 0, 158) ;
INSERT INTO sporuri VALUES (2011, 7, 3, 145, 0, 0, 0) ;
INSERT INTO sporuri VALUES (2011, 7, 4, 50, 15, NULL, 15) ;
INSERT INTO sporuri VALUES (2011, 7, 5, 130, 0, 0, 120) ;
INSERT INTO sporuri VALUES (2011, 7, 6, 110, 147, 0, 0) ;
INSERT INTO sporuri VALUES (2011, 7, 7, 60, 210, 0, 0) ;
INSERT INTO sporuri VALUES (2011, 7, 8, 130, 0, 15, 0) ;
INSERT INTO sporuri VALUES (2011, 7, 9, 140, 100, 77, 0) ;
INSERT INTO sporuri VALUES (2011, 7, 10, 200, 0, 0, 120) ;

Care sunt persoanele i lunile pentru


care nu s-a calculat (nu se cunoate)
sporul pentru condiii deosebite ?
SELECT S.M arca,N um ePren,
Com part, An, Luna
FRO M personalp IN N ER JO IN
sporuris O N p.M arca= s.M arca
W H ERE SporCD IS N U LL

Care sunt persoanele i lunile pentru


care sporul pentru condiii deosebite a
fost zero ?
SELECT S.M arca, N um ePren, Com part, An, Luna
FRO M personalp IN N ER JO IN sporuris O N
p.M arca= s.M arca
W H ERE SporCD = 0
O RD ER BY N um ePren,
An, Luna

Care este totalul sporurilor fiecrui


angajat pe luna iulie 2011 ? (1)
SELECT s.M arca, N um ePren,Com part,
SporVechim e, SporN oapte, SporCD ,
AlteSpor, SporVechim e + SporN oapte +
SporCD + AlteSpor AS TotalSporuri
FRO M personalp IN N ER JO IN sporuris
O N p.M arca= s.M arca
W H ERE An = 2011 AN D Luna= 7

Care este totalul sporurilor fiecrui


angajat pe luna iulie 2011 ? (2)

Convertirea NULL-itilor
Orice valoare NULL poate fi nlocuit cu o
alt valoare, numeric, ir, dat ...
Funcii: COALESCE, VALUE, NVL
Ex: COALESCE (SporCD, 0)

Dac valoarea lui SporCD nu este NULL, funcia


COALESCE o returneaz ca atare
Dac valoarea lui SporCD este NULL, funcia
COALESCE returneaz valoarea 0

Alte ex: COALESCE (Localitate, Iasi),


COALESCE (DataFact, CURRENT_DATE)

Care este totalul sporurilor fiecrui


angajat pe luna iulie 2011 ? (3)
SELECT s.M arca, N um ePren,Com part,
SporVechim e, SporN oapte,SporCD , AlteSpor,
CO ALESCE(SporVechim e,0) +
CO ALESCE(SporN oapte,0) +
CO ALESCE(SporCD ,0) +
CO ALESCE(AlteSpor,0) AS TotalSporuri
FRO M personalp IN N ER JO IN sporuris
O N p.M arca= s.M arca
W H ERE An = 2011 AN D Luna= 7

Care este totalul sporurilor fiecrui


angajat pe luna iulie 2011 ? (4)

Grupri i NULL-iti
S se determine, n tabel FACTURI, de
cte ori apare fiecare valoarea distinct
a atributului Obs
SELECT COALESCE(Obs,'* fara observatii
*'),
COUNT(*) FROM facturi
GROUP BY Obs
ORDER BY Obs NULLS LAST

Jonciunea extern

Jonciunea extern n SQL-92


La stnga
SELECT *
FROM r1 LEFT OUTER JOIN r2 ON r1.C=r2.C

La dreapta
SELECT *
FROM r1 RIGHT OUTER JOIN r2 ON r1.C=r2.C

Total
SELECT *
FROM r1 FULL OUTER JOIN r2 ON r1.C=r2.C

Explicatii detaliate despre


jonctiunea externa

http://stackoverflow.com/questions/38549/differ
ence-between-inner-and-outer-joins

Care sunt codurile potale la


care nu se afl niciun client ?
SELECT *
FRO M coduri_postale CP LEFT O U TER JO IN
clientiC O N CP.CodPost = C.CodPost
W H ERE C.CodPost IS N U LL

Sporuri de noapte pe luna mai


2011 (1)
SELECT An, Luna, p.M arca, N um ePren, SporN oapte
FRO M personalp IN N ER JO IN sporuris
O N p.M arca= s.M arca AN D An= 2011 AN D
Luna= 5
O RD ER BY N um ePren, An, Luna

Sporuri de noapte pe luna mai 2011


(2)
SELECT An, Luna, p.M arca, N um ePren, SporN oapte
FRO M personalp LEFT O U TER JO IN sporuris
O N p.M arca= s.M arca AN D An= 2011 AN D Luna= 5
O RD ER BY N um ePren, An, Luna

Sporuri de noapte pe luna mai 2011


(3)
SELEC T C O ALESC E(An,2011) AS An, CO ALESCE(Luna,5) AS
Luna, p.M arca, N um ePren,
CO ALESCE (SporN oapte,0) AS SporN oapte
FR O M personalp LEFT O U TER JO IN sporuris
O N p.M arca= s.M arca AN D An= 2011 AN D Luna= 5
O RD ER BY N um ePren, An, Luna

Sporuri de noapte pe lunile MAI


i IUNIE 2011 (1)
SELEC T p.M arca, N um ePren,
CO ALESC E (s5.SporN oapte,0) AS "SpN oapteM AI",
CO ALESC E (s6.SporN oapte,0) AS
"SpN oapteIU N IE"
FRO M personalp
LEFT O U TER JO IN sporuris5 O N
p.M arca= s5.M arca
AN D s5.An= 2011 AN D s5.Luna= 5
LEFT O U TER JO IN sporuris6 O N
p.M arca= s6.M arca
AN D s6.An= 2011 AN D s6.Luna= 6

Sporuri de noapte pe lunile MAI


i IUNIE 2011 (2)

Sporuri de noapte pe trimestrul


2 2011, lunar i cumulat (1)
SELECT p.M arca, N um ePren,
CO ALESCE (s4.SporN oapte,0) AS "SpN oapte APRILIE",
CO ALESCE (s5.SporN oapte,0) AS "SpN oapte M AI",
CO ALESCE (s6.SporN oapte,0) AS "SpN oapte IU N IE",
CO ALESCE (s4.SporN oapte,0) + CO ALESCE (s5.SporN oapte,0)
+ CO ALESCE (s6.SporN oapte,0) AS "SpN oapte TRIM .2"
FRO M personalp
LEFT O U TER JO IN sporuris4 O N p.M arca= s4.M arca
AN D s4.An= 2011 AN D s4.Luna= 4
LEFT O U TER JO IN sporuris5 O N p.M arca= s5.M arca
AN D s5.An= 2011 AN D s5.Luna= 5
LEFT O U TER JO IN sporuris6 O N p.M arca= s6.M arca
AN D s6.An= 2011 AN D s6.Luna= 6
O RD ER BY N um ePren

Sporuri de noapte pe trimestrul


2 2011, lunar i cumulat (2)

Blocuri decizionale (teste)


multiple

Vestea proast: n SQL nu exist IF

Vestea bun: exist CASE care joac pe post de


IF multiplu:

IF condiie THEN bloc-lansat-cnd-condiia-este-ndeplinit


ELSE bloc-lansat-cnd-condiia-NU-este-ndeplinit END IF

CASE
WHEN condiie1 THEN bloc-lansat-cnd-condiia1-estendeplinit
WHEN condiie2 THEN bloc-lansat-cnd-condiia2-estendeplinit
...
ELSE bloc-lansat-cnd-niciuna-dintre-condiiile-de-mai-susNU-este-ndeplinit

END

Ci dintre clieni sunt din


localitatea Iai i ci din afara
Iaului ? (1)
SELECT CASE Loc
W H EN 'Iasi'TH EN 'D in Iasi'
ELSE 'D in afara Iasului'
EN D AS Pozitionare,
CO U N T(*) AS N rClienti
FRO M clientic IN N ER JO IN coduri_postale cp
O N c.CodPost = cp.CodPost
G RO U P BY CASE Loc
W H EN 'Iasi'TH EN 'D in Iasi'
Iasului'
EN D

ELSE 'D in afara

Ci dintre clieni sunt din


localitatea Iai i ci din afara
Iaului ? (2)

Ci dintre clieni sunt din


localitatea Iai i ci din afara
Iaului ? (3)
SELECT

CASE
WHEN Loc = 'Iasi' THEN 'Din Iasi'
ELSE 'Din afara Iasului'
END AS Pozitionare,
COUNT(*) AS NrClienti
FROM clienti c INNER JOIN coduri_postale cp
ON c.CodPost = cp.CodPost
GROUP BY CASE WHEN Loc = 'Iasi' THEN 'Din Iasi'
ELSE 'Din afara Iasului' END

Grupri, NULL i CASE


S se afieze cte facturi au observaii (adic
valoarea atributului Obs este nenul) i cte
nu au
SELECT CASE W H EN CO ALESCE(O bs,'') = ''
TH EN '* fara observatii*'
ELSE '* cu observatii*'EN D
AS Situatie, CO U N T(*)
FRO M facturi
G RO U P BY CASE W H EN CO ALESCE(O bs,'') = ''
TH EN '* fara observatii*' ELSE '* cu observatii*'
EN D

Sporuri de noapte pe luna mai


2011 (4)
(fr COALESCE)
SELECT CASE W H EN s.An IS N U LL TH EN 2011 ELSE s.An
EN D AS An,
CASE W H EN s.Luna IS N U LL TH EN 5 ELSE s.Luna
EN D AS Luna,
p.M arca, N um ePren,
CASE W H EN SporN oapte IS N U LL TH EN 0

ELSE

s.SporN oapte EN D AS SporN oapte


FRO M personalp LEFT O U TER JO IN sporuris
O N p.M arca= s.M arca AN D An= 2011 AN D Luna= 5
O RD ER BY N um ePren, An, Luna

Ci angajai au primit, n iulie


2011, spor pentru condiii
deosebite i ci nu ?

SELECT C ASE W H EN SporCD > 0 TH EN

'Au spor C D ' ELSE 'N u au spor CD ' EN D AS


"Situatie", CO U N T(*) AS N r
FRO M sporuri
W H ERE An= 2011 AN D Luna= 7
G RO U P BY C ASE W H EN SporCD > 0 TH EN
'Au spor C D 'ELSE 'N u au spor C D 'EN D

Care este valoarea vnzrilor din


fiecare zi a sptmnii (I) ?
SELECT TO _CH AR(D ataFact, 'day') AS Zi_Saptam ina,
SU M (Cantitate * PretU nit * (1+ ProcTVA)) AS Vinzari_Zi_Sapt
FRO M facturif IN N ER JO IN liniifact lf O N f.N rfact= lf.N rFact
IN N ER JO IN produse p O N lf.CodPr= p.CodPr
G RO U P BY TO _CH AR(D ataFact, 'day')
O RD ER BY

CASE

W H EN RTRIM (TO _CH AR(D ataFact, 'day')) IN ('luni', 'm onday') TH EN 1


W H EN RTRIM (TO _CH AR(D ataFact, 'day')) IN ('m ari', 'tuesday') TH EN 2
W H EN RTRIM (TO _CH AR(D ataFact, 'day')) IN ('m iercuri', 'w ednesday') TH EN 3
W H EN RTRIM (TO _CH AR(D ataFact, 'day')) IN ('joi', 'thursday') TH EN 4
W H EN RTRIM (TO _CH AR(D ataFact, 'day')) IN ('vineri', 'friday') TH EN 5
W H EN RTRIM (TO _CH AR(D ataFact, 'day')) IN ('sm bt', 'saturday') TH EN 6
W H EN RTRIM (TO _CH AR(D ataFact, 'day')) IN ('dum inic', 'sunday') TH EN 7 EN D

Care este valoarea vnzrilor din


fiecare zi a sptmnii (II) ?

Scadena facturilor n sept 2011 este de 16


zile. Dac ns cade ntr-o smbt sau
duminic, atunci scadena se mut n lunea
imediat urmtoare
SELECT NrFact, DataFact AS "Data Emiterii",
DataFact + INTERVAL '16' DAY AS "Data Scadenta",
EXTRACT (DOW FROM DataFact + INTERVAL '16' DAY) AS "Zi (nr) sapt scad.",
TO_CHAR(DataFact + INTERVAL '16' DAY, 'DAY') AS "Zi sapt.scad.",
CASE WHEN EXTRACT (DOW FROM DataFact + INTERVAL '16' DAY) = 6
THEN DataFact + INTERVAL '18' DAY

ELSE

CASE WHEN EXTRACT (DOW FROM DataFact + INTERVAL '16' DAY) = 0


THEN DataFact + INTERVAL '17' DAY
ELSE DataFact + INTERVAL '16' DAY
END
END AS "Data scad.corectata"
FROM facturi
WHERE TO_CHAR(datafact, 'MM-YYYY') = '09-2011'

Scadena de 16 zile; dac ns cade


smbta sau duminica, atunci se mut n
lunea urmtoare (2)