Documente Academic
Documente Profesional
Documente Cultură
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Training
Version: 3 / 19.09.2019
1
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Contents
Training .............................................................................................................................................. 1
2
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
I. Notiuni Generale
Pentru a putea defini structura unei baze de date si a stoca informatiile avem nevoie de un
software care sa realizeze toate functiile pe care aceste nevoi le implica. Un astfel de soft se
numeste sistem de gestiune a bazelor de date, prescurtat in romana SGBD si in engleza
DBMS (Database Management System).
Un DBMS implementeaza functiile necesare pentru diferitele aspecte ale lucrului cu bazele de
date:
Accesarea informatiilor dintr-o baza de date se poate realiza de catre un utilizator (un profesor
insereaza notele de la examen) sau de catre o aplicatie (o aplicatie de monitorizare a unui
server web insereaza intr-o baza de date paginile accesate, tipul de browser folosit).
Utilizatorul interfateaza cu DBMS prin intermediul unui client – o aplicatie (SQL Server
Management Studio).
Aplicatiile care acceseaza bazele de date o fac indirect, prin intermediul DBMS. Atunci cand
dorim, spre exemplu, sa cream o baza de date sau sa inseram informatii in baza de date , vom
solicita softului DBMS sa faca acest lucru, trimitand comenzile corespunzatoare. DBMS
cunoaste formatul in care a fost memorata informatia si are acces direct la datele in cauza.
3
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Aplicatia client nu poate avea intotdeauna acces la date (deseori clientii ruland pe alta masina
decat DBMS. Clientul acceseaza datele independent de aspectele fizice ale stocarii datelor pe
HDD sau in RAM.
Avand in vedere ca DBMS ofera servicii clientilor in baza cererilor formulate de catre acestia, el
contine un modul care actioneaza ca server de baze de date.
Cererea trimisa de catre clienti serverului de baze de date poarta denumirea de interogare
(query).
Unul dintre beneficiile importante pe care le ofera un DBMS este decuplarea modalitatii fizice de
structurare a datelor (exemplu: organizarea, locatia si denumirea fisierelor) de modalitatea de
accesare si manipulare a lor. Utilizatorul care beneficiaza de serviciile unui DBMS nu vede (si
nici nu doreste sa stie) aspectele low-level ale stocarii informatiei, ci doreste o viziune logica a
datelor memorate care sa ii permita usoara lor introducere, extragere si prelucrare.
In acest scop, DBMS pune la dispozitia utilizatorului fie o interfata grafica, fie un limbaj care sa ii
permita acestuia interactiunea cu datele si facilitatile conexe acestora. Limbajul folosit in cazul
bazelor de date relationale este SQL (Sructured Query Language).
SQL este un limbaj ce contine intructiuni pentru definirea si modificarea structurii bazelor de
date, accesarea si manipularea datelor si controlul accesului la date. El a fost creat la inceputul
anilor ”70 la IBM si folosit initial ca baza intr-unul dintre produsele acestei firme. Ulterior, in
1986, el este standardizat de catre ANSI (American National Standards Institute) si apoi de
catre ISO (International Organization for Standardization).
Desi fiecare dintre aceste pachete software implementeaza limbajul SQL, fiecare dintre ele
prezinta abateri de la standard sau extensii ale limbajului, care, pe de o parte duc la
performante mai bune sau o mai mare usurinta de utilizare, dar pe de alta parte introduc
incompatibilitati intre diversele softuri DBMS.
4
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
O baza de date relationala este un ansamblu de informatie compus dintr-unul sau mai multe
tabele. Modalitatea fizica de stocare a datelor tine de softul DBMS folosit (diferind de la un
DBMS la altul). Gratie limbajului SQL, clientul poate manipula datele independent de aspectele
fizice ale stocarii datelor.
Informatiile sunt stocate in tabele. O baza de date poate contine zero sau mai multe tabele.
Tabele (relatii)
Exemplu: Dorim sa cream o tabela in care sa stocam informatii despre facturi. Coloanele
necesare sunt: Id_Factura, Id_Client, Data_Factura, Valoare. Avem 4 coloane obligatorii si un
numar variabil de randuri. Vom impune pentru fiecare coloana tipul de date corespunzator.
Dupa crearea tabelei, se vor insera datele. Acestea respecta constrangerile de tip de data
impuse la crearea tabelei.
Coloane (atribute)
5
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Desi in definitia unei tabele, coloanele sunt create intr-o anumita ordine, la extragerea datelor
din baza de date, ele pot fi reordonate.
Randuri (inregistrari)
Un rand al unei tabele reprezinta un ansamblu de valori (date), cate una corespunzatoare
fiecarei coloane. Fiecare valoare dintr-o tabela se afla la intersectia unei linii cu o coloana, o
valoare este unic identificata odata ce am specificat: serverul, baza de date, tabela, coloana
si randul.
Conceptul NULL
T-SQL este un dialect al standardului SQL. Toti furnizorii de baze de date, inclusiv Microsoft au
implementat dialect SQL ca principal limbaj in manipularea datelor in platformele lor de baze de
date. Pe de alta parte, nucleul limbajului este acelasi.
Utilizand standard SQL este best parctice. Codul este portabil si usor de implementat in alte
platforme.
Un exemplu cand alegem sa lucram in standard SQL folosim operatorul <> (diferit) fata de
operatorul nonstandard != (diferit).
6
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Management Studio este un software lansat pentru prima data cu versiunea Microsoft SQL
Server 2005, utilizat pentru configurarea, organizarea si administrarea componentelor Microsoft
SQL Server. Tool-ul include atat partea de interactiune grafica, cat si editare de scripturi in
vederea lucrului cu obiectele serverului.
Cu ajutorul Object Explorer se ierarhizeaza obiectele fiecarei instante SQL Server: Databases,
Security etc.
7
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Baza de date captureaza toate vanzarile realizate intr-o companie, clientii companiei, precum si
tranzactiile dintre companie si furnizorii sai.
8
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Toate aceste informatii sunt stocate in diferite tabele. Tabelele au denumiri, in functie de ce
informatii detin. Scopul crearii mai multor tabele este de a da userului o imagine de ansamblu
asupra procesului de business si ce rapoarte sunt necesare si pot fi extrase. Relatiile dintre
tabele ne redau flow-ul de business.
Tabelele sunt organizate pe diferite scheme: dbo, HR, Production, Sales, Stats.
Tabele
Tabelele sunt obiectele in care stocam informatiile. Au un numar definit de coloane si un numar
variabil de randuri. Fiecare coloana are un nume, tip de date si constrangeri, daca este cazul.
Tipuri de date
Exact numeric:
- Bigint
- Int
- Smallint
9
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
- Tinyint
p – reprezinta numarul total de digits stocati, la stanga si la dreapta de punctul zecimal. Prezicia
trebuie sa fie un numar intre 1 (minim) si 38 (maxim). Precizia default este 18.
s – reprezinta numarul de digits stocati la dreapta punctului zecimal. Scala poate fi un numar
intre 0 si p. Scala default este 0.
1-9 5
10-19 9
20-28 13
29-38 17
- Money
10
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
- Date (yyyy-mm-dd)
Calendar Gregorian
- Datetime
- Smalldatetime
11
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Calendar Gregorian
(Does not include the complete range of years.)
Character string:
- Char(n) – lungime fixa egala cu n (numarul de caractere permise). n poate lua valori
intre 1 si 8000. Dimensiunea este egala cu n bytes.
- Varchar(n) – lungime variabila egala cu n. Dimensiunea este egala cu n bytes plus 2
bytes.
- Varchar(max) – max indica maximul dimensiunii egal cu 2^31-1 byte (2GB).
- Nchar(n) – n poate lua o valoare intre 1 si 4000 (2 character set). Dimensiunea este de
doua ori n bytes. Este dimensiune fixa.
- Nvarchar(n) - n poate lua o valoare intre 1 si 4000 (2 character set). Dimensiunea este
de doua ori n bytes. Este dimensiune variabila.
- Nvarchar(max) - max indica maximul dimensiunii egal cu 2^31-1 byte (2GB).
12
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Sintaxa unei interogari SQL este urmatoarea, precum si ordinea de scriere a clauzelor:
1. SELECT <<coloane>>
2. FROM <<tabele>>
3. WHERE <<conditii>>
4. GROUP BY <<agregari>>
13
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
1. FROM <<tabele>>
2. WHERE <<conditii>>
3. GROUP BY <<agregari>>
4. HAVING <<conditii pe agregari>>
5. SELECT <<coloane>>
6. ORDER BY <<ordonarea datelor>>
Exemplu:
SELECT Extragem
country Tara
, YEAR(hiredate) AS yearhired Anul angajarii
, COUNT(*) AS numemployees Numarul total de anagajati
FROM HR.Employees Din tabela Employees, schema HR
WHERE hiredate >= '20030101' Cu conditia ca data angajarii sa fie cel putin 1
ianuarie 2003
GROUP BY country Grupam datele dupa tara
, YEAR(hiredate) si anul angajarii pentru ca avem o functie de
agregare (COUNT)
HAVING COUNT(*) > 1 Consideram doar tarile si anii de angajare cu
mai mult de 1 angajat
ORDER BY country Ordonam datele dupa tara
, yearhired DESC; si anul angajarii
Rezultat:
14
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: Deoarece ORDER BY este evaluat dupa SELECT, atunci aliasul pentru extragerea anului
(yearhired) este recunoscut, ceea ce inseamna ca putem ordona dupa alias (redenumire
coloanei)
- Prima clauza evaluata este clauza FROM. In clauza FROM este (sunt) indicat(e) tabelul
(tabelele). Daca se extrag date din mai multe tabele, atunci apare si notiunea de JOIN si
fiecare tabel va primi un alias (un nume). JOIN-urile se vor discuta ulterior.
select * FROM HR.Employees afiseaza toate datele din tabela HR.Employees (9 randuri)
- Cea dea doua clauza evaluata este clauza WHERE, clauza care ne permite sa filtram
randurile din tabel(e). Randurile care sunt evaluate la False sau la Unknown nu sunt
afisate.
select *
FROM HR.Employees
WHERE hiredate >= '20030101'
(7 randuri)
Obs: Clauza WHERE nu recunoaste alias-urile pentru ca este evaluata inaintea clauzei
SELECT. In cadrul clauzei SELECT se stabilesc alias-urile pentru coloane.
15
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
SELECT country, YEAR(hiredate) AS yearhired FROM HR.Employees WHERE yearhired >= 2003
Msg 207, Level 16, State 1, Line 2
Invalid column name 'yearhired'.
- A treia clauza evaluata este clauza GROUP BY. Clauza GROUP BY permite gruparea
randurilor in functie de coloanele specificate (country si year(hiredate)).
SELECT country
, YEAR(hiredate) AS yearhired
, count(*) Nr_Angajati
FROM HR.Employees
WHERE hiredate >= '20030101'
GROUP BY country
, YEAR(hiredate)
- Cea de-a patra clauza evaluata este clauza HAVING. Clauza ne permite sa extragem
doar gruparile cu mai mult de un angajat. Sunt afisate doar randurile unde conditia este
True (nu sunt afisate randurile unde conditia este evaluata la False sau Unknown).
SELECT country
, YEAR(hiredate) AS yearhired
, count(*) Nr_Angajati
FROM HR.Employees
WHERE hiredate >= '20030101'
GROUP BY country
, YEAR(hiredate)
HAVING COUNT(*) > 1
- Cea de-a cincea clauza evaluata este clauza SELECT. In cadrul clauzei, mai intai se
evalueaza expresiile si atribuie alias-uri coloanelor rezultate. Dupa evaluarea expresiilor,
se evalueaza clauza DISTINCT, daca aceasta este specificata. DISTINCT extrage
inregistrarile unice.
16
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
- Clauza ORDER BY este ultima evaluata, implicit dupa clauza SELECT, ceea ce
inseamna ca in cadrul lui ORDER BY putem utiliza alias-uri sau numarul de coloane.
SELECT country
, YEAR(hiredate) AS yearhired
, count(*) Nr_Angajati
FROM HR.Employees
WHERE hiredate >= '20030101'
GROUP BY country
, YEAR(hiredate)
HAVING COUNT(*) > 1
ORDER BY 1 , 2 DESC;
Clauza FROM
Clauza FROM este prima clauza evaluata din cadrul unei interogari.
- Este clauza unde sunt indicate tabele din care se extrag informatiile
- Este clauza unde sunt aplicatii operatorii de tip JOIN.
Exemplu:
Unde:
- HR – schema
- Employees – tabela
Obs: In anumite cazuri, schema poate fi omisa, insa se va considera schema default: dbo
Exemplu:
17
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
In cadrul clauzei FROM se pot specifica si alias-uri pentru tabele. Alias-ul este un nume scurt
asociat tabelei, de obicei litera cu care incepe tabelul.
Obs: Daca un tabel primeste alias, atunci numele intreg al tabelului nu mai este recunoscut.
Clauza SELECT
18
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Clauza SELECT este ultima clauza evaluata. Are doua roluri principale:
Exemple:
Obs: Returnarea tuturor coloanelor nu este best practice. Trimitand mai multe date decat este
nevoie, poate avea un impact negativ asupra performantei sistemului.
Exemplu:
19
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: Daca se omite virgula dintre firstname si lastname, atunci lastname devine alias pentru
coloana firstname.
Exemplu:
20
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Clauza DISTINCT este utilizata pentru a elimina randurile duplicate din rezultatul unei
interogari.
- Clauza DISTINCT
Una dintre diferentele dintre standard SQL si T-SQL este faptul ca in standard SQL nu poate
exista doar clauza SELECT fara clauza FROM, pe cand in T-SQL poate fi de sine statatoare
clauza SELECT.
21
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Exemplu:
Obs: Functia getdate() returneaza data si ora curente. ABC Company este intre apostrofuri
pentru ca este un text.
Delimitatori de identificare
Identificarea atributelor, schemelor, tabelelor sau a altor obiecte poate fi facuta cu ajutorul
delimitatorilor.
Utilizarea acestora este optionala atunci cand identificatorii sunt regulari: tabela Orders, schema
Sales, coloana OrderDate. Regula pentru identifcatorii regulari este: primul caracter trebuie sa
fie o litera de la A la Z (mica sau mare). Nu pot fi utilizate cuvinte cheie din T-SQL, nu pot exista
spatii si nici caractere speciale.
Daca identificatorii nu urmeaza regula de mai sus, atunci delimitatorii devin obligatorii si
identificatorii se numeste iregulari: coloana [Order Data], tabela ”Orders 2016”.
22
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Exercitii:
23
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Clauza WHERE este cea de-a doua clauza evaluata, dupa clauza FROM.
SELECT empid, firstname, lastname, country, region, city FROM HR.Employees WHERE region
='WA';
SELECT empid, firstname, lastname, country, region, city FROM HR.Employees WHERE region
<>'WA';
Obs: Daca selectam toti angajatii din tabela Employees fara sa filtram dupa regiune:
observam ca in coloana region aveam NULL si WA, iar cand interogarea a fost sa selectam toti
angajatii cu regiunea diferita de WA, rezultatul nu a fost cele 4 randuri cu NULL, ci 0 randuri.
24
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
NULL reprezinta „missing value”, nu o valoare NULL. Cand regiunea este NULL, operatorul
<> WA evalueaza predicatul la „unknown”, adica nu se cunoaste regiunea (nu a fost completata
in baza de date).
Pentru a returna toti angajatii care au regiunea diferita de WA, interogarea va fi construita astfel:
SELECT empid
, firstname
, lastname
, country
, region
, city
FROM HR.Employees
WHERE region <> 'WA'
OR region IS NULL;
Obs: Filtrarea datelor este un lucru foarte important pentru performanta interogarii. Filtrand
datele, inseamna ca tabela nu este scanata in intregime si astfel se reduce traficul in retea. O
alta metoda pentru a imbunatatii performanta unei interogarii este prin utilizarea indecsilor (se
va discuta mai tarziu).
SELECT custid
, companyname
, country
FROM [Training].[Sales].[Customers]
WHERE country='UK' or country='usa'
Exemplu: Sa se determine toti clientii din UK sau USA cu functia de Sales Representative.
25
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
SELECT custid
, companyname
, contacttitle
, country
FROM [Training].[Sales].[Customers]
WHERE (country='UK' or country='usa') and contacttitle='Sales Representative'
Obs: Intrucat clientii sunt fie din UK, fie din USA, dar indiferent de tara, au functia de Sales
Representative, atunci vom utiliza in filtrarea datelor si operatorul AND, pe langa operatorul OR.
Scrierea filtrelor se va face utilizand paranteze, pentru a reuni multimea clientilor din UK cu
multimea clientilor din USA, rezultand astfel o singura multime de clienti, asupra careia aplicam
urmatorul filtru, cel cu functia de Sales Representative, astfel restragem multimea rezultata.
Exemplu: Sa se determine toti clientii din UK cu functia de Sales Representative si clientii din
Canada cu functia de Accounting Manager.
SELECT custid
, companyname
, contacttitle
, country
FROM [Training].[Sales].[Customers]
WHERE (country='UK' and contacttitle='Sales Representative') or
(country='Canada' and contacttitle='Accounting Manager')
Exemplu: Sa se determine toti clientii care nu sunt din Spania, dar au functia fie de Marketing
Manager, fie de Sales Associate.
SELECT [custid]
,[companyname]
,[contacttitle]
,[country]
FROM [Training].[Sales].[Customers]
where country <> 'Spain'
and contacttitle in ('Marketing Manager','Sales Associate')
Rezultatul interogarii – 18 randuri.
26
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
SELECT [orderid]
,[custid]
,[empid]
,[orderdate]
FROM [Training].[Sales].[Orders]
where [orderdate]>='2008-01-01' and [orderdate]<='2008-12-31'
sau
SELECT [orderid]
,[custid]
,[empid]
,[orderdate]
FROM [Training].[Sales].[Orders]
where [orderdate] between '2008-01-01' and '2008-12-31'
Rezultatul interogarii – 270 de randuri
Exemplu: Sa se determine toate tranzactiile din 2006 de valoare cuprinsa intre 50 si 100.
SELECT [orderid]
,[custid]
,[empid]
,[orderdate]
,freight
FROM [Training].[Sales].[Orders]
where ([orderdate] between '2006-01-01' and '2006-12-31')
and freight between 50 and 100
Rezultatul interogarii – 32 de randuri
Obs: Scrierea filtrelor de tip date and time se va face in limbaj neutru. De exemplu, '20070212'
Intotdeauna este interpretat ymd. De asemenea, '2007-02-12' este scriere in limbaj neutru doar
daca coloana filtrata este tip: DATE, SMALLDATETIME, DATETIME, DATETIME2,
DATETIMEOFFSET.
SELECT empid, firstname, lastname FROM HR.Employees WHERE lastname LIKE 'D%';
27
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
SELECT empid, firstname, lastname FROM HR.Employees WHERE firstname LIKE '%A';
SELECT empid, firstname, lastname FROM HR.Employees WHERE firstname LIKE '%AR%';
Exemplu: Sa se determine toti clientii a caror regiune incepe cu W si numele regiunii are 2
caractere.
SELECT
custid
,companyname
,region
from [Sales].[Customers] where region like 'W_'
Clauza ORDER BY este ultima clauza evaluata, deci dupa clauza SELECT. Clauza ORDER BY
sorteaza datele ascendent (ASC) sau descendent (DESC).
Exemplu: Sa se determine toti angajatii din regiunea WA ordonati ascendent dupa oras.
28
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: Daca nu se specifica tipul de sortare (ASC sau DESC), atunci sortarea implicita va fi
ascendenta.
Exemplu: Sa se determine toti angajatii din regiunea WA ordonati descendent dupa oras.
Obs: Observam ca avem doi angajati din acelasi oras. Cei doi angajati nu sunt sortati intr-o
anumite ordine.
Exemplu: Sa se determine toti angajatii din regiunea WA ordonati descendent dupa oras si id-ul
de angajat.
Obs: Tinand cont ca ORDER BY este evaluata dupa clauza SELECT, putem specifica in cadrul
interogarii numarul de coloana (coloane) dupa care se doreste sortarea.
29
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: De asemenea, din aceleasi considerente de evaluare a clauzei ORDER BY, putem sorta
datele si dupa alias-uri.
Exemplu: Sa se determine toti angajatii si anul nasterii lor, angajati din regiunea WA; angajatii
sa fie ordonati descendent dupa anul nasterii.
Obs: Pot fi sortate datele si in functie de coloane care nu sunt afisate in SELECT, dar sunt
prezente in tabele.
Exemplu: Sa se determine toti angajatii din regiunea WA. Angajatii vor fi sortati ascendent dupa
data nasterii.
Obs: Daca sortarea datelor se va face in functie de coloana ce contine NULL, atunci NULL-urile
vor fi afisate primele si apoi valorile non-null.
30
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
- Numar de randuri
Cu ajutorul optiunii TOP putem filtra un numar specificat de randuri. Optiunea TOP se
mentioneaza imediat dupa clauza SELECT.
Exemplu: Sa se determine cele mai recente 3 tranzactii din tabela Orders in functie de data
tranzactiei.
Obs: Optiunea TOP se utilizeaza impreuna cu clauza ORDER BY. In caz contrar se extrag 3
randuri aleatorii din tabela mentionata.
- Procent
In mod similar se pot extrage primele 10% tranzactii in functie de valoarea tranzactiei.
31
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Rezultatul interogarii – 83 de randuri (in total, in tabela Orders sunt 830 randuri).
- With Ties
In cazul in care ultimul rand rezultat are valoarea coloanei mentionata in clauza ORDER BY
egala cu a altor randuri, pentru a returna si celelalte randuri, se utilizeaza optiunea WITH TIES.
Exemplu: Sa se determine cele mai recente 3 tranzactii din tabela Orders in functie de data
tranzactiei. Daca ultimul ultima tranzactie are aceeasi data cu a altor tranzactii, sa se returneze
toate tranzactiile.
Exercitii:
1. Sa se ruleze scriptul 02. Create db Bank.sql (scriptul creeaza o baza de date cu mai
multe tabele relationate)
32
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
33
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Clauza GROUP BY
Clauza GROUP BY permite gruparea datelor in mai multe seturi de date, iar, ulterior aceste
seturi date pot fi prelucrate utilizand: functii de agregare si filtrari.
Functii de agregare
- COUNT (coloana) – numara cate valori not null exista in coloana mentionata
- COUNT (*) – numara toate randurile
- COUNT(distinct coloana) – numara cate valori distincte exista in coloana mentionata
- SUM(coloana) – insumeaza valorile din coloana mentionata
- MAX(coloana) – determina valoarea maxima din coloana mentionata
- MIN(coloana) – determina valoarea minima din coloana mentionata
- AVG(coloana) – determina media aritmetica a valorilor nenule din coloana mentionata
Exemplu:
SELECT
count([shipregion]) Nr_Valori_NOTNULL
,count(*) Nr_randuri
,count(distinct [shipregion]) Nr_Valori_Distinct
FROM [Training].[Sales].[Orders]
Obs: Datorita faptului ca nu a fost specificat un set de atribute de grupare, interogarea de mai
sus returneaza un singur set de date.
SELECT [shipregion]
,count(*) Nr_Tranzactii
FROM [Training].[Sales].[Orders]
group by [shipregion]
order by [shipregion]
34
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs:
Setul de atribute de grupare este format dintr-un singur atribut: shipregion. Este utilizata functia
de agregare COUNT(*).
Daca nu se specifica functia de agreare, rezultatul interogarii este tot 20 rows, insa nu va mai fi
afisat numarul de randuri pentru fiecare regiune.
SELECT [shipregion]
--,count(*) Nr_Tranzactii
FROM [Training].[Sales].[Orders]
group by [shipregion]
order by [shipregion]
SELECT [shipregion]
,year(orderdate) An_tranzactie
,count(*) Nr_Tranzactii
FROM [Training].[Sales].[Orders]
group by [shipregion]
,year(orderdate)
order by [shipregion]
35
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
select
shipregion
,shipcity
,count(*) Nr_Tranzactii
,sum(freight) Total_Val
,avg(freight) Media_Arit
,max(freight) Max_Val
,min(freight) Min_Val
from [Training].[Sales].[Orders]
group by
shipregion
,shipcity
select
shipcity
,year(orderdate) An_Tranzactie
,count(*) Nr_Tranzactii
,sum(freight) Total_Val
,avg(freight) Media_Arit
from [Training].[Sales].[Orders]
where freight>=50
group by
shipcity
,year(orderdate)
order by 2
36
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: year(orderdate) extrage anul din data tranzactiei (orderdate). Conditia de freight>=50
extrage doar randurile din tabel unde freight este de cel putin 50. Setul de atribute de grupare
este format din shipcity si se regaseste atat in clauza select, cat si in clauza group by. Order by
2 (este specificat numarul coloanei) este posibil deoarece clauza order by se evalueaza dupa
clauza select, deci se cunosc coloanele extrase.
Clauza HAVING
Clauza HAVING se utilizeaza atunci cand se filtreaza seturi de date. In cadrul clauzei having,
conditiile sunt la nivel de functii de agregare. Clauza WHERE este la nivel de randuri dintr-o
tabela, pe cand clauza HAVING este la nivel de set de date.
select
shipcity
,year(orderdate)
,sum(freight) Total_Val
from [Training].[Sales].[Orders]
group by
shipcity
,year(orderdate)
having sum(freight) between 3000 and 5000
order by 2
37
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
select
shipcity
,year(orderdate)
,sum(freight) Total_Val
from [Training].[Sales].[Orders]
where freight<=1000
group by
shipcity
,year(orderdate)
having sum(freight) between 3000 and 5000
order by 2
Exercitii:
38
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Adesea, datele necesare in rapoarte fac parte din mai multe tabele. Un mediu de baze date cu
cat este mai mult normalizat (se va discuta ulterior), cu atat mai multe tabele avem. Tabelele
sunt relationate intre ele prin chei: in tabela principala avem PRIMARY KEY, in tabela de
legatura avem FOREIGN KEY.
PRIMARY KEY
Cheia primara a unei tabele reprezinta ansamblul minim de campuri (sau doar un singur camp)
care identifica in mod unic o inregistrare dintr-o tabela. Pe o tabela poate exista cel mult o cheie
primara.
Campul/ ansamblul de campuri pe care se defineste cheia primara nu admite NULL si trebuie
sa contina date unice (exemplu: numarul de factura, codul de client, codul de produs).
T-SQL suporta 3 tipuri de joinuri: cross, inner si outer pentru a extrage informatii din mai multe
tabele.
CROSS JOIN
Cross Join este cel mai simplu tip de join si creeaza produsul cartezian dintre cele doua tabele
date. Daca tabela T1 contine m randuri si tabela T2 contine n randuri, atunci, rezultatul cross
join-ului va fi mxn randuri.
Exemplu: Sa se asocieze categoriile de produse toti furnizorii.
select
c.categoryname
,s.companyname
FROM [Training].[Production].[Categories] c
cross join Training.[Production].[Suppliers] s
39
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
INNER JOIN
Inner join returneaza partea comuna din doua tabele. Legatura dintre cele doua tabele se
realizeaza prin campul/campurile comun/comune.
Exemplu: Sa se determine toate produsele din categoria Seafood cu pretul de cel putin 15.
select
*
from [Production].[Categories] c
inner join Production.Products p on c.categoryid=p.categoryid
where c.categoryname='Seafood' and p.unitprice>=15
40
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
- Cele doua tabele au alias-uri: Categories alias c, products alias p. Motivul adaugarii
alias-urilor este utilizarea coloanei comune categoryid, pentru a stii din ce tabela se
preia coloana categoryid.
OUTER JOINs
LEFT OUTER JOIN (LEFT JOIN) – returneaza toate randurile din tabela din stanga si doar
randurile din tabela din dreapta care se regasesc si in prima tabela.
Exemplu: Sa se determine toti clientii si facturile acestora. Anumiti clienti nu au inca facturi.
select
c.custid
, c.companyname
, o.orderid
, o.orderdate
from Training.sales.Customers c
left join Training.[Sales].[Orders] o on o.custid=c.custid
41
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Exercitii:
1. Sa se determine clientii unici care au conturi cu balanta intre 1000 si 5000. – 2 clienti
2. Sa se modifice interogarea anterioara astfel incat sa se afiseze cati clienti unici au balanta
intre 1000 si 5000. – 2
3. Sa se afiseze clientii si conturile de tip depozit (sunt doua inner join-uri) – 5 conturi
4. Sa se determine clientii, conturile si tranzactiile de tip Plata Salariu. – 3 randuri
5. Sa se determine toate conturile pe care nu exista tranzactii efectuate.- 3 randuri
6. Sa se determine toate tipurile de tranzactii pentru care nu exista tranzactii. – 1 rand
7. Sa se determine la nivel de tip cont si tip tranzactie: cate tranzactii sunt, cati clienti distincti
au efectuate tranzactiile, cate conturi distincte exista pentru aceste tranzactii. – 6 randuri
42
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
- Forma simpla
- Forma de cautare
CASE – forma simpla: compara o expresie de intrare (o coloana in general) cu multiple valori
de comparatie stabilite prin expresia WHEN.
Exemplu: Sa se verifice levelurile fiecarui sef din firma astfel: daca managerul este 1 atunci
level 1, daca managerul este 2, atunci level 2, daca managerul este 3 atunci level 3 altfel other
level.
SELECT
empid
,lastname
,firstname
,case mgrid
when 1 then 'Level 1'
when 2 then 'Level 2'
when 3 then 'Level 3'
else 'Other Level'end Level
FROM [Training].[HR].[Employees]
43
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
select
productid
,productname
,case
when unitprice<=30 then 'intre 0 si 30'
when unitprice<=60 then 'intre 31 si 60'
else 'peste 61' end as Interval_Pret
from Training.Production.Products
Functia COALESCE – este o abreviere a expresiei CASE. Coalesce este o functie standard,
nu asociata T-SQL.
Functia COALESCE accepta o lista de expresii de intrare si returneaza prima expresie nenull
sau NULL, daca toate expresiile sunt NULL.
Exemplu: Sa se afiseze fax-ul pentru fiecare client. In cazul in care fax-ul nu este completat
(NULL), atunci sa se afiseze numarul de telefon.
select
custid
,companyname
,fax
,phone
,coalesce(fax,phone) as Contact
from Training.Sales.Customers
44
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Functia ISNULL – este o abreviere a expresiei CASE. Functia ISNULL este nonstandard.
Functia ISNULL are doua argumente: expresia considerata pentru verificare daca este NULL si
expresia care va fi returnata in cazul in care prima expresie este NULL.
Exemplu: Sa se afiseze textul „nu are fax” pentru clientii care nu au faxul completat.
select
custid
,companyname
,fax
,phone
,isnull(fax,'nu are fax') as Contact
from Training.Sales.Customers
Obs: Rezultatul functiei COALESCE va avea data type-ul expresiei rezultat. Rezultatul functiei
ISNULL va avea data type-ul primei expresii.
45
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
46
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
select
year(hiredate) Anul_Anagajarii
,count(*) Nr_Angajati
from Training.hr.Employees
group by year(hiredate)
Exemplu: Sa se determine pentru fiecare comanda: anul, luna si ziua. Sa se filtreze infromatiile
doar pentru anul 2006. Sa se ordoneze datele ascendent dupa luna, ascendent dupa zi.
select
orderid
,year(orderdate) An_Comanda
,month(orderdate) Luna_Comanda
,day(orderdate) Zi_Comanda
from Training.Sales.Orders
where year(orderdate)=2006
order by month(orderdate), day(orderdate)
47
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Functia DATEDIFF returneaza diferenta dintre doua date calendaristice. Unitatea de masura
pentru diferenta este data ca input de catre utilizator.
select
empid
,lastname
,firstname
,datediff(yyyy,birthdate,hiredate) Varsta
from Training.hr.Employees
48
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Exemplu: Sa se determine pentru fiecare angajat anul in care va primi un bonus de fidelitate
stiind ca acest bonus se primeste la 5 ani de la angajare.
select
empid
,lastname
,firstname
,hiredate
,dateadd(yyyy,5,hiredate) Data_Bonus
,year(dateadd(yyyy,5,hiredate)) An_Bonus
from Training.hr.Employees
49
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
SELECT
[custid]
,[companyname]
,[contactname]
,charindex(',',contactname,1) Pozitie_Virgula
FROM [Training].[Sales].[Customers]
Exemplu: Sa se extraga in doua coloane separate numele si prenumele clientilor, din coloana
contactname.
SELECT
[custid]
,[companyname]
,[contactname]
,charindex(',',contactname,1) Pozitie_Virgula
,substring(contactname,1,charindex(',',contactname,1)-1) LastName
,substring(contactname,charindex(',',contactname,1)+1,len(contactname)-
charindex(',',contactname,1)) FirstName
FROM [Training].[Sales].[Customers]
50
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: Primul pas a fost indetificarea pozitiei virgulei. Pentru a extrage LastName, se vor extrage
toate caracterele situate inaintea virgulei. Pentru a extrage FirstName, se vor extrage toate
caracterele situate dupa virgula.
Exercitii:
Rezultat interogare:
2. Sa se modifice interogarea anterioara astfel incat, pentru fiecare client sa fie afisate cate
conturi se regasesc in fiecare interval mentionat.
Rezultat interogare:
51
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Rezultat interogare:
52
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
5. Sa extraga din tabela Shippers numele celor 3 companii: GVSUA, ETYNR, ZHISN.
Rezultatul interogarii:
Rezultat interogare:
53
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Tabele temporare
SQL Server utilizeaza doua tipuri de tabele temporare: locale si globale. Ambele tipuri de tabele
sunt stocate in baza de date tempdb.
Tabelele temporare locale sunt prefixate cu # (exemplu: #mytable), iar tabelele temporare
globale sunt prefixate cu ## (exemplu: ##mytable).
Tabelele temporare locale sunt vizibile doar pe parcursul sesiunii unui singur user. Dupa
incheierea sesiunii, acestea sunt sterse.
Tabelele temporare gloable sunt vizibile pentru toate sesiunile si pentru toti userii. Se sterg
automat dupa inchiderea ultimei sesiuni in care sunt folosite.
Tabelele temporare (atat locale, cat si globale) se comporta la fel ca orice tabel permanent din
baza de date, exceptand baza de date unde sunt stocate (tempdb) si faptul ca acestea sunt
sterse automat la inchiderea sesiunii.
Exemplu: Sa se determine intr-o tabela temporara toti clientii din Londra si pentru acestia prima
tranzactie efectuata. Pentru tranzactiile extrase, sa se determine total discount (discount *
cantitate * pret) si total incasari (cantitate * pret).
SELECT c.custid
,c.city
,min(o.orderid) Min_OrderId
into #minorder
FROM [Training].[Sales].[Customers] c
inner join Training.Sales.Orders o on o.custid=c.custid
where c.city='London'
group by
c.custid
,c.city
54
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
select
m.*
, sum(od.discount * od.qty * od.unitprice) Total_Discount
, sum(od.qty * od.unitprice) Total_Valoare
from #minorder m
inner join Training.Sales.OrderDetails od on od.orderid=m.Min_OrderId
group by
m.custid
,m.city
,m.Min_OrderId
Exemplu: Sa se determine acelasi lucru ca mai sus, dar sa se utilizeze tabela temporara globala
##minorder.
SELECT c.custid
,c.city
,min(o.orderid) Min_OrderId
into ##minorder
FROM [Training].[Sales].[Customers] c
inner join Training.Sales.Orders o on o.custid=c.custid
where c.city='London'
group by
c.custid
,c.city
select
m.*
, sum(od.discount * od.qty * od.unitprice) Total_Discount
, sum(od.qty * od.unitprice) Total_Valoare
from ##minorder m
inner join Training.Sales.OrderDetails od on od.orderid=m.Min_OrderId
group by
m.custid
,m.city
,m.Min_OrderId
55
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: Diferenta dintre cele doua tabele: #minorder, ##minorder este faptul ca cea dea doua
tabela poate fi vizualizata si intr-o alta sesiune.
Exercitii:
1. Sa se determine intr-o tabela temporara locala conturile cu balanta cea mai mica. Pentru
aceste conturi sa se extraga toate tranzactiile efectuate.
2. Sa se determine intr-o tabela temporara globala conturile de tip Credit. Pentru aceste
conturi sa se determine toate tranzactiile din 2010 si 2011.
3. Sa se determine intr-o tabela temporara locala prima tranzactie efectuata de catre
fiecare client. Pentru aceste tranzactii, sa se determine separat valoarea tranzactiilor si
tipul acestora.
Tabele derivate – sunt subinterogari care au ca rezultat un tabel. Tabelele derivate sunt
utilizate in joinuri cu tabelele din baza de date.
Exemplu:
Sa se determine cel mai scump produs al fiecarui furnizor, iar pentru produsele determinate sa
se afiseze toate detaliile produselor, precum si numele categoriei din care fac parte.
56
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
SELECT
p.*
,c.categoryname
from [Training].[Production].[Products] p
inner join Training.Production.Categories c on c.categoryid=p.categoryid
inner join
(SELECT
supplierid
,max(unitprice) Max_UnitPrice
FROM [Training].[Production].[Products]
group by
supplierid) p2 on p2.supplierid=p.supplierid and
p2.Max_UnitPrice=p.unitprice
Exercitii:
Baza de date Bank:
1. Sa se determine tranzactia cu valoarea cea mai mica pentru fiecare cont de tip Credit.
Pentru aceste tranzactii sa se afiseze toate detaliile din tabela tranzactii, precum si
descrierea tranzactiei si numele clientului.
Rezolvare:
select
t.*
,c.Nume
,tt.Descriere
from Bank.dbo.tranzactii t
inner join Bank.dbo.tiptranzactii tt on tt.IdTipTranzactie=t.IdTipTranzactie
inner join
(select
t.Cont
,min(t.Valoare) Min_Valoare
from Bank.dbo.tranzactii t
inner join bank.dbo.conturi c on c.cont=t.cont
inner join bank.dbo.tipcont tc on tc.IdTipCont=c.IdTipCont
where tc.Descriere='credit'
group by
57
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
CTE – Common Table Expression – este un concept similar cu tabelele derivate. Tabele CTE
sunt vizibile doar pe parcursul rularii statementului in care sunt definite. Un tabel de tip expresie
este format din 3 parti:
Sintaxa CTE:
WITH nume_CTE as
Exemplu: Sa se determine pentru fiecare client, contul cu balanta cea mai mare.
with CTE_bal
as nume
(select
idclient,
max(balanta) balanta
from bank.dbo.conturi
group by Interogrea din interior
idclient
)
select
c.cont,
c.idclient,
c.Balanta
from bank.dbo.conturi c Interogarea din exterior
inner join cte_bal cc on
c.Balanta=cc.balanta and
c.IdClient=cc.IdClient
58
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Exercitii:
1. Sa se determine pentru toti clientii cu suma totala comandata de peste 1000, toate
comenzile.
Rezolvare:
with cte_cust
as
(
select
c.custid
,sum(od.qty*od.unitprice) Total_Comenzi
from Training.Sales.Customers c
inner join Training.Sales.Orders o on o.custid=c.custid
inner join Training.Sales.OrderDetails od on od.orderid=o.orderid
group by c.custid
having
sum(od.qty*od.unitprice)>1000
)
select
o.*
from cte_cust cc
inner join Training.Sales.Orders o on o.custid=cc.custid
59
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
UNION ALL: opereaza intre doua sau mai multe seturi de date. UNION ALL uneste rezultatele
mai multor seturi date si pastreaza inregistrarile multiplicate.
select
city
,region
,country
from Training.Sales.Customers
union all
select
city
,region
,country
from Training.hr.Employees
Obs: Structura celor doua interogari este identica. Rezultatul final al reuniunii rezultatelor celor
doua interogarii contine inregistrari care se multiplica.
60
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
UNION: opereaza intre doua sau mai multe seturi de date. UNION uneste rezultatele mai multor
seturi date si elimina inregistrarile multiplicate.
select
city
,region
,country
from Training.Sales.Customers
union
select
city
,region
,country
from Training.hr.Employees
INTERSECT – operatorul returneaza inregistrarile comune dintre doua sau mai multe seturi de
date.
Exemplu: Sa se determine toate orasele, regiunile si tarile comune ale clientilor si ale
angajatilor.
select
city
,region
,country
from Training.Sales.Customers
intersect
select
city
,region
,country
from Training.hr.Employees
61
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
EXCEPT – operatorul returneaza diferenta dintre doua seturi de date, inregistrarile continute de
primul set de date care nu se regasesc in al doilea set.
Exemplu: Sa se determine toate orasele, regiunile si tarile clientilor din care nu fac parte
angajatii.
select
city
,region
,country
from Training.Sales.Customers
except
select
city
,region
,country
from Training.hr.Employees
Exercitii:
Rezolvare:
62
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
with cte_inv as
select
i.Customer_Id,
i.Registration_store_id,
min(i.invoice_no) Min_Invoice_No,
min(i.invoice_date) Min_Data_Factura
from Vanzari.dbo.invoices i
inner join Vanzari.dbo.products p on p.Art_no=i.Art_No
where i.Registration_store_id in (11,12,13)
and p.Art_Desc='FILTRU MAXTRA'
group by i.Customer_Id,
i.Registration_store_id
select
ci.Customer_Id,
ci.Registration_store_id,
c.Customer_Name,
cc.Lvl1_Desc,
cc.Lvl4_Desc,
sum(i.qty*i.price_net) Valoare
from cte_inv ci
inner join Vanzari.dbo.invoices i on i.Customer_Id=ci.Customer_Id
and
i.Registration_store_id=ci.Registration_store_id
and
i.Invoice_Date=ci.Min_Data_Factura
and
i.Invoice_No=ci.Min_Invoice_No
inner join vanzari.dbo.customers c on c.Customer_Id=ci.Customer_Id and
c.Registration_Store_Id=ci.Registration_store_id
inner join vanzari.dbo.customers_category cc on cc.Lvl4_id=c.Lvl4_Id
group by
ci.Customer_Id,
ci.Registration_store_id,
c.Customer_Name,
cc.Lvl1_Desc,
cc.Lvl4_Desc
having sum(i.qty*i.price_net)>=50
63
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
select
i.Customer_Id,
i.Registration_store_id,
min(i.invoice_no) Min_Invoice_No,
min(i.invoice_date) Min_Data_Factura
into #inv
from Vanzari.dbo.invoices i
inner join Vanzari.dbo.products p on p.Art_no=i.Art_No
where i.Registration_store_id in (11,12,13)
and p.Art_Desc='FILTRU MAXTRA'
group by i.Customer_Id,
i.Registration_store_id
select
ci.Customer_Id,
ci.Registration_store_id,
c.Customer_Name,
cc.Lvl1_Desc,
cc.Lvl4_Desc,
sum(i.qty*i.price_net) Valoare
from #inv ci
inner join Vanzari.dbo.invoices i on i.Customer_Id=ci.Customer_Id
and
i.Registration_store_id=ci.Registration_store_id
and
i.Invoice_Date=ci.Min_Data_Factura
and
i.Invoice_No=ci.Min_Invoice_No
inner join vanzari.dbo.customers c on c.Customer_Id=ci.Customer_Id and
c.Registration_Store_Id=ci.Registration_store_id
inner join vanzari.dbo.customers_category cc on cc.Lvl4_id=c.Lvl4_Id
group by
ci.Customer_Id,
ci.Registration_store_id,
c.Customer_Name,
cc.Lvl1_Desc,
cc.Lvl4_Desc
having sum(i.qty*i.price_net)>=50
64
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
select
ci.Customer_Id,
ci.Registration_store_id,
c.Customer_Name,
cc.Lvl1_Desc,
cc.Lvl4_Desc,
sum(i.qty*i.price_net) Valoare
from
(
select
i.Customer_Id,
i.Registration_store_id,
min(i.invoice_no) Min_Invoice_No,
min(i.invoice_date) Min_Data_Factura
from Vanzari.dbo.invoices i
inner join Vanzari.dbo.products p on p.Art_no=i.Art_No
where i.Registration_store_id in (11,12,13)
and p.Art_Desc='FILTRU MAXTRA'
group by i.Customer_Id,
i.Registration_store_id
) ci
inner join Vanzari.dbo.invoices i on i.Customer_Id=ci.Customer_Id
and
i.Registration_store_id=ci.Registration_store_id
and
i.Invoice_Date=ci.Min_Data_Factura
and
i.Invoice_No=ci.Min_Invoice_No
inner join vanzari.dbo.customers c on c.Customer_Id=ci.Customer_Id and
c.Registration_Store_Id=ci.Registration_store_id
inner join vanzari.dbo.customers_category cc on cc.Lvl4_id=c.Lvl4_Id
group by
ci.Customer_Id,
ci.Registration_store_id,
c.Customer_Name,
cc.Lvl1_Desc,
cc.Lvl4_Desc
having sum(i.qty*i.price_net)>=50
65
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
SELECT
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
,SUM(I.QTY*I.PRICE_NET) TOTAL_VANZARI
FROM customers C
INNER JOIN invoices I ON I.Registration_store_id=C.Registration_Store_Id AND
I.Customer_Id=C.Customer_Id
WHERE C.Registration_Store_Id=11
GROUP BY
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
HAVING SUM(I.QTY*I.PRICE_NET)>500
INTERSECT
SELECT
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
,SUM(I.QTY*I.PRICE_NET) TOTAL_VANZARI
FROM customers C
INNER JOIN invoices I ON I.Registration_store_id=C.Registration_Store_Id AND
I.Customer_Id=C.Customer_Id
WHERE I.Buying_Store_id=11
GROUP BY
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
HAVING SUM(I.QTY*I.PRICE_NET)>=1000
66
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
SELECT
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
,SUM(I.QTY*I.PRICE_NET) TOTAL_VANZARI
FROM customers C
INNER JOIN invoices I ON I.Registration_store_id=C.Registration_Store_Id AND
I.Customer_Id=C.Customer_Id
WHERE C.Registration_Store_Id=11
GROUP BY
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
HAVING SUM(I.QTY*I.PRICE_NET)>5000
except
SELECT
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
,SUM(I.QTY*I.PRICE_NET) TOTAL_VANZARI
FROM customers C
INNER JOIN invoices I ON I.Registration_store_id=C.Registration_Store_Id AND
I.Customer_Id=C.Customer_Id
WHERE I.Buying_Store_id=11
GROUP BY
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
HAVING SUM(I.QTY*I.PRICE_NET)>=10000
SELECT
67
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
,avg(I.QTY*I.PRICE_NET) TOTAL_VANZARI
FROM customers C
INNER JOIN invoices I ON I.Registration_store_id=C.Registration_Store_Id AND
I.Customer_Id=C.Customer_Id
WHERE C.Registration_Store_Id=11
GROUP BY
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
HAVING avg(I.QTY*I.PRICE_NET)>=500
union all
SELECT
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
,avg(I.QTY*I.PRICE_NET) TOTAL_VANZARI
FROM customers C
INNER JOIN invoices I ON I.Registration_store_id=C.Registration_Store_Id AND
I.Customer_Id=C.Customer_Id
WHERE C.Registration_Store_Id=18
GROUP BY
C.Registration_Store_Id
,C.Customer_Id
,C.Customer_Name
HAVING avg(I.QTY*I.PRICE_NET)>=300
68
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Flow de business:
- un client suna departamentul Call Center pentru a primi o oferta de concediu=> Clientul
este stocat in tabela Clienti
- Agentul din Call Center creeaza o rezervare pentru propunerea catre client=>
Rezervarea este creata si stocata in tabela Orders
- Clientul confirma sau nu rezervarea. Daca va confirma rezervarea => Rezervarea
confirmata este stocata in tabela Orders_details
- Daca se confirma rezervarea, atunci se stiu detaliile despre rezervare=> tabela Hotels,
tabela Cities, tabela Countries
Conform exemplului de business de mai sus, se pot identifica urmatorele tabele: Customers,
Countries , Cities, Hotels, Orders, Orders_details.
Creare tabele
69
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: Coloanele idcustomer si idcountry nu accepta NULL. Cheia primara (PK) pentru tabela
Customers este idcustomer. Coloanele pentru care se va seta PK nu accepta NULL. Pentru o
tabela se poate defini cel mult o cheie primara.
USE Reservations
GO
GO
70
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
GO
GO
GO
Alterare tabele
Un tabel odata creat poate fi modificat utilizand comanda ALTER. In acest mod pot fi adaugate,
sterse, modificate coloane.
Exemple:
71
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Constrangeri tabele
Exemple:
72
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: Daca tabela Customers contine deja date, iar coloana Name are deja null-uri, atunci
adaugarea constragerii NOT NULL nu va functiona. Mai intai se vor completa NULL-urile
existente si apoi se va aplica constrangerea de NOT NULL pentru viitorii clienti inserati in
tabela.
2) Sa se modifice tabela Hotels, astfel incat, campul idCity sa admita doar date unice.
OBS: Adaugarea constrangerii de UNIQUE pentru IdCity inseamna din punct de vedere
business ca 2 hoteluri nu pot fi din acelasi oras. De exemplu, un lant hotelier are un singur hotel
in fiecare oras, Ramada ar putea fi un exemplu in acest sens.
3) Sa se stearga primary key-ul din tabela Cities. Sa se adauge primary key pe tabela
Cities.
73
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Exemple:
74
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
- Object Explorer / baza de date Reservations / click dreapta Database Diagrams / New
Database Diagram
Obs: Daca pentru fiecare tabela au fost adaugate FOREIGN KEYS, atunci digrama si
relatiile dintre tabele se creaza implicit.
75
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: Daca pentru fiecare tabela nu au fost adaugate FOREIGN KEYS, atunci digrama si
relatiile dintre tabele trebuie create de catre utilizator.
76
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Obs: campurile conectate trebuie sa fie identice ca si: tip, contrangeri. Numele nu este
obligatoriu sa fie identic, insa best practice este sa se pastreze acelasi nume.
77
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Exercitii:
Locatii
Clienti
Masini
Angajati
78
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Denumire Varchar(100)
Functie Varchar(50)
IdLocatie Int Nu admite NULL FK cu referinta catre tabela
IdLocatie
Contracte
- Minim 4 tabela
79
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
80
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
INSERT
- INSERT Values
- INSERT Select
- INSERT Exec – se va discuta ulterior
- SELECT Into
INSERT Values
Exemplu: Sa se insereze doi clienti noi in tabela Clienti din baza de date Bank. Primul client
inserat va avea id-ul 400 si se va numi Client 4. Cel de-al doilea client inserat va avea id-ul 500
si se va numi Client 5.
(1 row(s) affected)
(1 row(s) affected)
INSERT Select
Exemplu: Sa se creeze o tabela temporara cu numele ##clienti care va avea doua coloane:
IdClient int not null si Nume_Client varchar(20). Campul IdClient va avea constrangerea de PK.
Sa se insereze toti clientii din tabela Bank.dbo.Clienti in tabela ##clienti.
81
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
from Bank.dbo.clienti
(5 row(s) affected)
SELECT Into
Exemplu: Sa se insereze toate conturile clientilor: Client 1 si Client 2 intr-o tabela temporara
locala. Odata cu conturile se va afisa si numele clientului.
select
c.Nume
,cc.IdClient
,cc.Cont
,cc.Balanta
into #conturi_clienti
from bank.dbo.clienti c
inner join bank.dbo.conturi cc on c.IdClient=cc.IdClient
where c.nume in ('Client 1','Client 2')
(6 row(s) affected)
82
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
UPDATE
Vom construi 3 tabele, copii ale tabelelor existente Customers, Orders si OrderDetails:
MyCustomers, MyOrders, MyOrderDetails
Construirea celor 3 tabele a fost realizata utilizand comanda SELECT Into.
Use Training;
GO
Sintaxa:
UPDATE tabela
SET Col1=expresia1,
Col2=expresia2
83
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
WHERE conditii
Randurile care vor fi evaluate la TRUE in ceea ce priveste clauza WHERE vor fi updatate. Daca
nu este specificata clauza WHERE, atunci vor fi updatate toate randurile din tabela specificata.
Exemplu: Sa se modifice discountul pentru factura cu numarul 10251 astfel incat, discountul va
fi crescut cu 5%.
select *
from Sales.MyOrderDetails
where orderid=10251
update sales.MyOrderDetails
set discount=discount+0.05
where orderid=10251
(3 row(s) affected)
Exemplu: Sa se modifice discountul adaugand 5% pentru toate facturile clientilor din Norway.
select
od.orderid
84
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
,od.productid
,od.discount
,c.custid
,c.companyname
,c.country
from Sales.MyOrderDetails od
inner join sales.MyOrders o on o.orderid=od.orderid
inner join sales.MyCustomers c on c.custid=o.custid
where c.country='Norway'
Obs: este un singur client cu mai multe comenzi, fiecare comanda avand un numar de produse
cu 0 discount.
update od
set od.discount=od.discount+0.05
from Sales.MyOrderDetails od
inner join sales.MyOrders o on o.orderid=od.orderid
inner join sales.MyCustomers c on c.custid=o.custid
where c.country='Norway'
select
od.orderid
,od.productid
,od.discount
,c.custid
,c.companyname
,c.country
from Sales.MyOrderDetails od
85
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
DELETE si TRUNCATE
T-SQL detine doua comenzi pentru stergerea datelor dintr-o tabela: DELETE si TRUNCATE
DELETE
Comanda DELETE sterge fie datele dintr-o tabela in intregime, fie doar anumite randuri care
sunt evaluate la TRUE conform uneia sau mai multor conditii.
Exemplu: Sa se stearga toate randurile din tabela MyOrderDetails unde productid=11 (se
presupune ca acest produs a fost adaugat dintr-o eroare pe anumite facturi si trebuie sters).
delete
from Sales.MyOrderDetails
where productid=11
86
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
select *
from Sales.MyOrderDetails
where productid=11
delete
from Sales.MyOrderDetails
delete o
from sales.MyOrders o
inner join sales.MyCustomers c on c.custid=o.custid
where c.country='Norway'
(6 row(s) affected)
Obs: Se verifica daca mai sunt comenzi pentru clientii din Norway.
select *
from sales.MyOrders o
inner join sales.MyCustomers c on c.custid=o.custid
where c.country='Norway'
Obs: Clientii din Norway nu au fost stersi, doar comenzile acestora au fost sterse.
select *
from sales.MyCustomers
where country='Norway'
87
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Daca se doreste si stergerea clientilor din Norway, atunci, dupa stergerea comenzilor se poate
rula comanda de delete asupra tabelei MyCustomers cu conditia: country='Norway'
TRUNCATE
Comanda TRUNCATE sterge toate randurile dintr-o tabela. Nu permite conditii pentru a sterge
doar anumite randuri.
- DELETE permite stergerea anumitor randuri dintr-o tabela, TRUNCATE sterge toate
datele dintr-o tabela
- TRUNCATE este mai rapida decat DELETE, pentru ca scrierea in Transaction Log se
face doar pentru paginile dealocate, in timp ce DELETE scrie in Transaction Log datele
care sunt sterse
- DELETE nu reseteaza identity. TRUNCATE reseteaza identity
- DELETE sterge utilizand JOIN-uri, ceea ce inseamna ca tine cont de FK. TRUNCATE
nu este permisa daca o tabela refrentiaza catre alta tabela
- DELETE are nevoie pentru user de dreptul de DELETE. TRUNCATE are nevoie pentru
user de dreptul de ALTER
2. Sa se insereze toate conturile din tabela Bank.dbo.Cont intr-o tabela noua MyAccounts
3. Sa se stearga toate conturile cu balanta NULL din tabela MyAccounts.
88
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
89
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Creare VIEW
VIEW-urile sunt obiecte ale bazei de date similare tabelelor. Cu ajutorul unui VIEW se pot
prezenta date dintr-unul sau mai multe tabele. Intr-un view se poate pastra logica de extragere
a datelor, astfel incat utilizatorul view-ului sa nu fie nevoit sa o retina.
select
year(o.orderdate) Year_Order,
sum(od.qty) Total_Qty
from sales.Orders o
inner join sales.OrderDetails od on od.orderid=o.orderid
group by
year(o.orderdate)
Obs:
c) View-ul creat se comporta la fel cu un tabel: se pot filtra datele, se pot face join-uri cu
alte tabele:
90
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
select *
from Sales.Qty_Orders
where Year_Order<>2006
Modificare VIEW
Modificarea / alterarea unui view se realizeaza in mod similar cu tabelele, utilizand comanda
ALTER.
Exemplu: Sa se modifice view-ul creat anterior (Sales.Qty_Orders) astfel incat informatiile sa fie
si la nivel de client (companyname).
select
c.companyname,
year(o.orderdate) Year_Order,
sum(od.qty) Total_Qty
from sales.Orders o
inner join sales.OrderDetails od on od.orderid=o.orderid
inner join sales.Customers c on c.custid=o.custid
group by
c.companyname,
year(o.orderdate)
Verificare
91
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Stergere VIEW
Comanda pentru a sterge un view din baza de date este: DROP view nume_view.
Exercitii:
Rezolvare:
1.
use bank;
go
as
select
c.Nume
,cc.Cont
,cc.Balanta
,t.IdTranzactie
,t.DataTranzactie
,t.Valoare
from dbo.clienti c
inner join dbo.conturi cc on c.IdClient=cc.IdClient
inner join dbo.tranzactii t on t.Cont=cc.Cont
where t.IdTipTranzactie<>1
2.
92
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
Corect:
use bank;
go
as
select
c.Nume
,cc.Cont
,cc.Balanta
,t.IdTranzactie
,t.DataTranzactie
,t.Valoare
from dbo.clienti c
inner join dbo.conturi cc on c.IdClient=cc.IdClient
inner join dbo.tranzactii t on t.Cont=cc.Cont
where t.IdTipTranzactie<>1
93
Data Training
Email: marcela.filip@datatraining.ro
Telefon: +40 721 61 27 85
Website: www.datatraining.ro
94