Sunteți pe pagina 1din 108

#SharingIsCaring

With Love - seria CA

Lab4
Sa se faca o lista toti angajatii care primesc o prima de 10% din salariu. Prima primesc numai
angajatii care nu au primit comision si au venit in companie in primele 6 luni ale anului in care
s-a angajat presedintele companiei.
Antetul listei este:
Nume_Presedinte, Data_ang_pres, Nume_ang, Data_ang, Salariu_ang, Comision, Prima
Se vor prezenta doua scripturi (metode de rezolvare) diferite.
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE.

Metoda 1:
SELECT
p.ename Nume_Presedinte,
p.hiredate Data_Ang_pres,
e.ename Nume_ang,
e.hiredate Data_Ang,
e.sal Salariu_ang,
e.comm Comision,
e.sal / 10 Prima
FROM emp p, emp e
WHERE
p.job = 'PRESIDENT'
AND NVL(e.comm, 0) = 0
AND EXTRACT(YEAR FROM e.hiredate) = EXTRACT(YEAR FROM p.hiredate)
AND EXTRACT(MONTH FROM e.hiredate) <= 6

Metoda 2:
SELECT
p.ename Nume_Presedinte,
p.hiredate Data_Ang_pres,
e.ename Nume_ang,
e.hiredate Data_Ang,
e.sal Salariu_ang,
e.comm Comision,
e.sal / 10 Prima
FROM emp p, emp e
WHERE
p.job = 'PRESIDENT'
AND NVL(e.comm, 0) = 0
AND EXTRACT(YEAR FROM e.hiredate) = EXTRACT(YEAR FROM p.hiredate)
AND EXTRACT(MONTH FROM e.hiredate) BETWEEN 1 AND 6

METODA 3
select p.ename "Nume_Presedinte", p.hiredate "Data_ang_pres",
a.ename "Nume_ang", a.hiredate "Data_ang", a.sal "Salariu_ang",
nvl(a.comm, 0) "Comision", a.sal*0.1 "Prima"
from emp p, emp a
where lower(p.job) like 'president'
and nvl(a.comm, 0) = 0
and extract(year from a.hiredate) = extract(year from p.hiredate)
and (extract(month from a.hiredate) >= 1 and extract(month from a.hiredate) <= 6);

METODA 4
define prima = 0.1*a.sal;
select p.ename "Nume_Presedinte", p.hiredate "Data_ang_pres",
a.ename "Nume_ang", a.hiredate "Data_ang", a.sal "Salariu_ang",
nvl(a.comm, 0) "Comision", &prima "Prima"
from emp p, emp a
where lower(p.job) like 'president'
and nvl(a.comm, 0) = 0
and substr(a.hiredate, 8, 2) = substr(p.hiredate, 8, 2)
and (extract(month from a.hiredate) between 1 and 6);

Selectati angajatii care s-au angajat in ultimele 4 luni ale anului, intre anii 1981 si 1983, nu 
primesc comision si lucreaza ca analisti . Se va afisa si data semnarii contractului de 
angajare, stiind ca aceasta a fost urmatoarea zi de luni dupa data angajarii. Se va afisa 
numele concatentat cu functia (ex. "FORD is ANALYST"), functia, salariul anual (concatenat 
cu sirul 'USD'), comisionul (daca e nul se va afisa 0), data semnarii contractului (in format cu 
luna si anul complet, ex.'24-DECEMBER-1982') si se va ordona alfabetic dupa nume.  
Antetul listei este nume_func, salariu_anual, comision, data_contract. 
Se vor prezenta doua scripturi (metode de rezolvare) diferite.  
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 

alter session set NLS_DATE_FORMAT='DD-MONTH-YYYY';


-- metoda 1
select
concat(concat(e.ename, ' is '), e.job) Nume_ang,
e.job Functie,
concat(e.sal * 12, ' USD') "Salariu_anual",
nvl(e.comm, 0) "Comision",
e.hiredate "Data contract"
from
emp e
where
e.job = 'ANALYST' and
(extract(year from e.hiredate) >= 1981 and extract(year from e.hiredate) <= 1983) and
(extract(month from e.hiredate) = 12 or
extract(month from e.hiredate) = 11 or
extract(month from e.hiredate) = 10 or
extract(month from e.hiredate) = 9)
order by e.ename;

-- metoda 2
select
ename || ' is ' || job Nume_ang,
job Functie,
sal*12 || ' ' || 'USD' "Salariu_anual",
nvl(comm, 0) "Comision",
hiredate "Data contract"
from
emp
where
job like 'ANALYST' and
(extract(year from hiredate) between 1981 and 1983) and
(extract(month from hiredate) between 9 and 12)
order by ename;

Selectati angajatii care s-au angajat in ultimele 4 luni ale anului, intre anii 1981 si 1983, nu 
primesc comision si lucreaza ca analisti . Se va afisa si data semnarii contractului de 
angajare, stiind ca aceasta a fost urmatoarea zi de luni dupa data angajarii. Se va afisa 
numele concatentat cu functia (ex. "FORD is ANALYST"), functia, salariul anual (concatenat 
cu sirul 'USD'), comisionul (daca e nul se va afisa 0), data semnarii contractului (in format cu 
luna si anul complet, ex.'24-DECEMBER-1982') si se va ordona alfabetic dupa nume. 
Antetul listei este nume_func, salariu_anual, comision, data_contract. 
Se vor prezenta doua scripturi (metode de rezolvare) diferite. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 
Metoda 1:

select ename||' is '||job "nume_func",


concat(to_char((sal * 12 + nvl(comm, 0))), 'USD') "salariu_anual",
nvl(comm, 0) "comision",
to_char(next_day(hiredate, 'MONDAY'), 'DD-MONTH-YYYY') "data_contract"
from emp
where
extract(month from hiredate) > 8 and
extract(year from hiredate) between 1981 and 1983 and
nvl(comm, 0) = 0 and
job like 'ANALYST'
order by "nume_func";

Metoda 2:
define salariu_anual = '(sal * 12 + nvl(comm, 0))';
define comision = '(nvl(comm, 0))';

select concat(concat(ename, ' is '), job) "nume_func",


concat(to_char(&salariu_anual), 'USD') "salariu_anual",
&comision "comision",
to_char(next_day(hiredate, 'MONDAY'), 'DD-MONTH-YYYY') "data_contract"
from emp
where
extract(month from hiredate) in (9, 10, 11, 12) and
extract(year from hiredate) between 1981 and 1983 and
&comision = 0 and
job = 'ANALYST'
order by "nume_func";

undefine salariu_anual;
undefine comision;

Lab5
Sa se faca o lista cu numele angajatului, numele departamentului, data angajării, numele șefului
și data angajării șefului
pentru angajații care au fost angajați în firmă după șeful lor și fac parte din departamentul
SALES. Ordonați descrescator
după numele angajatului. Se se rezolve folosind doua metode distincte de join.
Metoda 1:
SELECT
a1.ename "Nume Angajat",
d1.dname "Nume Departament",
a1.hiredate "Data Angajare",
a2.ename "Nume Sef",
a2.hiredate "Data Angajare Sef"
FROM
emp a1
INNER JOIN emp a2
ON a1.mgr = a2.empno AND
a1.hiredate > a2.hiredate
INNER JOIN dept d1
ON a2.deptno = d1.deptno AND d1.dname LIKE 'SALES'
ORDER BY a1.ename DESC;

Metoda 2:
SELECT
a1.ename "Nume Angajat",
d1.dname "Nume Departament",
a1.hiredate "Data Angajare",
a2.ename "Nume Sef",
a2.hiredate "Data Angajare Sef"
FROM
emp a1
NATURAL JOIN dept d1
JOIN emp a2
ON a1.mgr = a2.empno AND a1.hiredate > a2.hiredate
WHERE
d1.dname LIKE 'SALES'
ORDER BY a1.ename DESC;

Sa se faca o lista cu angajatii al caror sef are venitul lunar mai mare de 3000. Lista se va
ordona dupa numele subalternilor. Antetul listei este:

Nume_subaltern Venit_subaltern Grad_sal_subaltern Nume_sef Venit_sef


Grad_sal_sef

Se se rezolve folosind doua metode distincte de join.


METODA 1:

SELECT
a1.ename "Nume_subaltern",
a1.sal "Venit subaltern",
g1.grade "Grad_sal_subaltern",
a2.ename "Nume_sef",
a2.sal "Venit_sef",
g2.grade "Grad_sal_sef"
FROM
emp a1,
emp a2,
salgrade g1,
salgrade g2
WHERE
a1.mgr = a2.empno
AND a1.sal BETWEEN g1.losal AND g1.hisal
AND a2.sal BETWEEN g2.losal AND g2.hisal
AND a2.sal > 3000
ORDER BY 1

METODA 2:

SELECT
a1.ename "Nume_subaltern",
a1.sal "Venit_subaltern",
g1.grade "Grad_sal_subaltern",
a2.ename "Nume_sef",
a2.sal "Venit_sef",
g2.grade "Grad_sal_sef"
FROM
emp a1
INNER JOIN emp a2
ON a1.mgr = a2.empno
LEFT OUTER JOIN salgrade g2
ON a2.sal BETWEEN g2.losal AND g2.hisal
LEFT OUTER JOIN salgrade g1
ON a1.sal BETWEEN g1.losal AND g1.hisal
WHERE
a2.sal > 3000
ORDER BY 1
Sa se faca o lista cu numele angatilor, functia, numele sefului, functia sefului pentru toti 
angajatii care lucreaza in orasul DALLAS. Antetul listei va fi ang, func_ang, sef, func_sef. 
Lista se va ordona alfabetic dupa numele angajatilor. Se se rezolve folosind doua metode 
distincte de join. 
 
Metoda 1: 
select a1.ename "ang", a1.job "func_ang", a2.ename "sef", a2.job "func_sef" 
from emp a1, emp a2, dept d1 
where a1.mgr = a2.empno and d1.loc='DALLAS' and d1.deptno = a1.deptno 
order by a1.ename; 
 
Metoda 2: 
select a1.ename "ang", a1.job "func_ang", a2.ename "sef", a2.job "func_sef" 
from emp a1 
inner join emp a2 on a1.mgr = a2.empno 
inner join dept d1 on d1.deptno = a1.deptno 
where d1.loc='DALLAS' 
order by a1.ename; 
 
Sa se faca o lista cu angajatii al caror sef are venitul lunar mai mare de 3000. Lista se va 
ordona dupa numele subalternilor. Antetul listei este: 

Nume_subaltern Venit_subaltern Grad_sal_subaltern Nume_sef Venit_sef Grad_sal_sef 

Se se rezolve folosind doua metode distincte de join. 

Metoda 1 - folosind self join si left outer join 


 
select 
a1.ename Nume_subaltern, 
a1.sal + nvl(a1.comm, 0) Venit_subaltern, 
g1.grade Grad_sal_subaltern, 
a2.ename Nume_sef, 
a2.sal + nvl(a2.comm, 0) Venit_sef, 
g2.grade Grad_sal_sef 
from 
emp a1  
inner join emp a2 
left outer join salgrade g2 
on a2.sal between g2.losal and g2.hisal 
on a1.mgr = a2.empno 
 
left outer join salgrade g1 
on a1.sal between g1.losal and g1.hisal 
 
where  
a2.sal + nvl(a2.comm, 0) > 3000 
order by 
a1.ename; 
 
Metoda 2 - folosind self join si non-equis join 
 
select 
a1.ename Nume_subaltern, 
a1.sal + nvl(a1.comm, 0) Venit_subaltern, 
g1.grade Grad_sal_subaltern, 
a2.ename Nume_sef, 
a2.sal + nvl(a2.comm, 0) Venit_sef, 
g2.grade Grad_sal_sef 
from 
emp a1 
inner join salgrade g1 
on a1.sal between g1.losal and g1.hisal 
 
inner join emp a2 
inner join salgrade g2 
on a2.sal between g2.losal and g2.hisal 
on a1.mgr = a2.empno 
where  
a2.sal + nvl(a2.comm, 0) > 3000 
order by 
a1.ename; 
 
Selectati numele angajatilor, functia, numele departamentului, data angajarii si salariul pentru
toti angajatii care au acelasi salariu, s-au angajat intre anii 1981 si 1983 (inclusiv) si primesc
comision. Lista se va ordona alfabetic dupa nume. Se se rezolve folosind doua metode distincte
de join.

Metoda 1
SELECT e1.ENAME AS Nume, e1.JOB AS Functie, d1.dname AS Nume_departament,
e1.HIREDATE AS Data_angajarii, e1.SAL AS Salariu FROM emp e1
INNER JOIN emp e2 ON e1.SAL = e2.SAL
LEFT OUTER JOIN dept d1 ON e1.deptno = d1.deptno
WHERE e1.HIREDATE >= '01-JAN-81' AND e1.HIREDATE < '01-JAN-83' AND e1.COMM IS
NOT NULL AND e1.COMM <> 0 AND
e2.HIREDATE >= '01-JAN-81' AND e2.HIREDATE < '01-JAN-83' AND e2.COMM IS NOT NULL
AND e2.COMM <> 0
AND e1.ENAME <> e2.ENAME
ORDER BY e1.ENAME ASC;

Metoda 2

SELECT e1.ENAME AS Nume, e1.JOB AS Functie, d1.dname AS Nume_departament,


e1.HIREDATE AS Data_angajarii, e1.SAL AS Salariu FROM emp e1
JOIN emp e2 ON e1.SAL = e2.SAL
LEFT OUTER JOIN dept d1 ON e1.deptno = d1.deptno
WHERE e1.HIREDATE >= '01-JAN-81' AND e1.HIREDATE < '01-JAN-83' AND e1.COMM IS
NOT NULL AND e1.COMM <> 0 AND
e2.HIREDATE >= '01-JAN-81' AND e2.HIREDATE < '01-JAN-83' AND e2.COMM IS NOT NULL
AND e2.COMM <> 0
AND e1.ENAME <> e2.ENAME
ORDER BY e1.ENAME ASC;
 
Sa se faca o lista cu toti angajatii din firma, afisind numele, salariul si o coloana 
suplimentara numita RATE care ia valoarea 'Low' daca angajatul are o gradatie (grade) <3 si 
ia valoarea 'High' in caz contrar. Se vor afisa intai angajatii care au 'Low', urmati de cei care 
au 'High', ordonati apoi dupa salariu si dupa nume. Se se rezolve folosind doua metode 
distincte de join 
 
Metoda 1: in care am folosit atat INNER JOIN, cat si VERTICAL JOIN  
 
select e.ename, e.sal, 'Low' RATE  
from emp e 
INNER JOIN salgrade g  
ON e.sal BETWEEN g.losal AND g.hisal 
where g.grade < 3 
UNION  
select e.ename, e.sal, 'High' RATE  
from emp e 
INNER JOIN salgrade g  
ON e.sal BETWEEN g.losal AND g.hisal 
where g.grade >= 3 
order by 3 desc, 2, 1; 
 
Metoda 2: in care am folosit atat LEFT OUTER JOIN, cat si VERTICAL JOIN, metoda fara 
alias  
 
select emp.ename, emp.sal, 'Low' RATE  
from emp 
LEFT OUTER JOIN salgrade  
ON emp.sal BETWEEN salgrade.losal AND salgrade.hisal 
where salgrade.grade < 3 
UNION  
select emp.ename, emp.sal, 'High' RATE  
from emp  
LEFT OUTER JOIN salgrade  
ON emp.sal BETWEEN salgrade.losal AND salgrade.hisal 
where salgrade.grade >= 3 
order by 3 desc, 2, 1; 
 

Lab6
Pentru angajatii ce au aceeai paritate a lungimii numelui ca cea a sefului lor (daca nu au sef se
considera ca indeplinesc
aceasta conditie), faceti o lista cu:
- numele departamentului in care este seful, scris cu litere mari (NUME_DEPT_SEF)
- cate luni complete au lucrat in firma (LUNI_LUCRATE_ANG)
- initiala numelui lor, ca litera mica (INITIALA_ANG)
- ultima cifra a venitului lor (ULTIMA_CIFRA_SALARIU)
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL.
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE.

METODA 1:
SELECT
UPPER(d.dname) NUME_DEPT_SEF,
FLOOR(MONTHS_BETWEEN(SYSDATE, e.hiredate)) LUNI_LUCRATE_ANG,
LOWER(SUBSTR(e.ename, 1, 1)) INITIALA_ANG,
MOD(e.sal + NVL(e.comm, 0), 10) ULTIMA_CIFRA_SALARIU
FROM emp e, dept d, emp mng
WHERE e.mgr = mng.empno(+)
AND mng.deptno = d.deptno(+)
AND MOD(LENGTH(e.ename), 2) = MOD(LENGTH(NVL(mng.ename, e.ename)), 2);
METODA 2:
SELECT
UPPER(d.dname) NUME_DEPT_SEF,
TRUNC(MONTHS_BETWEEN(SYSDATE, e.hiredate)) LUNI_LUCRATE_ANG,
SUBSTR(LOWER(e.ename), 1, 1) INITIALA_ANG,
SUBSTR(TO_CHAR(e.sal + NVL(e.comm,0)), LENGTH(TO_CHAR(e.sal + NVL(e.comm, 0))),
1) ULTIMA_CIFRA_SALARIU
FROM emp e
LEFT JOIN emp mng
ON e.mgr = mng.empno
LEFT JOIN dept d
ON mng.deptno = d.deptno
WHERE MOD(LENGTH(e.ename), 2) = MOD(LENGTH(NVL(mng.ename, e.ename)), 2);

METODA 3:
SELECT UPPER(D1.DNAME) NUME_DEPT_SEF,
FLOOR(MONTHS_BETWEEN(SYSDATE, E1.HIREDATE)) LUNI_LUCRATE_ANG,
LOWER(SUBSTR(E1.ENAME, 1, 1)) INITIALA_ANG,
MOD(E1.SAL + NVL(E1.COMM, 0), 10) ULTIMA_CIFRA_SALARIU
FROM EMP E1, EMP E2, DEPT D1, DEPT D2
WHERE E1.MGR = E2.EMPNO and E1.DEPTNO = D1.DEPTNO
AND E2.DEPTNO = D2.DEPTNO AND
MOD(LENGTH(E1.ENAME), 2) = MOD(LENGTH(E2.ENAME), 2);

Sa se scrie o cerere SQL care face o lista cu toti angajatii, numarul de zile de concediu la care
au dreptul, calculat dupa urmatoarea formula: numarul de zile dintre data la care s-a angajat
persoana respectiva si ultima zi din luna in care s-a angajat persoana respectiva. Ordonati lista
crescator dupa numarul de zile de concediu.

Antetul listei este urmatorul:

​Nume_angajat, Data_angajare, Den_dep, Nr_zile_CO

​Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL.

Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE.

Metoda 1:

SELECT
a1.ename Nume_angajat,
a1.hiredate Data_angajare,
d.dname Den_dep,
ABS(a1.hiredate - LAST_DAY(TRUNC(a1.hiredate, 'MONTH'))) Nr_zile_CO
FROM
emp a1
INNER JOIN dept d
ON a1.deptno = d.deptno
ORDER BY 4

Metoda 2:

SELECT
a1.ename Nume_angajat,
a1.hiredate Data_angajare,
d.dname Den_dep,
EXTRACT(DAY from LAST_DAY(a1.hiredate)) - EXTRACT(DAY from a1.hiredate)
Nr_zile_CO
FROM
emp a1
LEFT OUTER JOIN dept d
ON a1.deptno = d.deptno
ORDER BY 4

Sa se scrie o cerere SQL care face o lista cu angajatii care au o vechime in firma mai mare de
un an. Pentru fiecare angajat se vor afisa: Numele angajatului, ultima litera din numele lui, ziua
in care s-a angajat acesta, vechimea lui in luni si numele departamenului urmat de 3 *. Ordonati
lista dupa vechime.
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL.
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 

Metoda 1

SELECT e.ENAME AS NUME, SUBSTR(e.ename, LENGTH(e.ename)) AS ULTIMA_LITERA,


e.hiredate AS ZI_ANGAJARE, MONTHS_BETWEEN(SYSDATE, e.hiredate) AS
VECHIME_LUNI, d.DNAME||'***' AS NUME_DEPARTAMENT
FROM EMP e
INNER JOIN dept d
ON e.deptno = d.deptno
WHERE MONTHS_BETWEEN(SYSDATE, e.hiredate) >= 12
ORDER BY hiredate ASC;
Metoda 2

SELECT e.ENAME AS NUME, SUBSTR(e.ename, LENGTH(e.ename)) AS ULTIMA_LITERA,


e.hiredate AS ZI_ANGAJARE, MONTHS_BETWEEN(SYSDATE, e.hiredate) AS
VECHIME_LUNI, CONCAT(d.DNAME, '***') AS NUME_DEPARTAMENT
FROM EMP e
INNER JOIN dept d
USING (deptno)
WHERE (SYSDATE - e.hiredate) >= 365
ORDER BY hiredate ASC;

Sa se calculeze o prima pentru angajatii care 


- au lungimea numelui mai mica sau egal cu 5 
- au venit in firma in acelasi an cu seful lor. 
Prima se calculeaza dupa urmatoarea formula salariu * c * |log2(n)/((n^2+1)*sin(n^2+1))| 
unde 
- n este vechimea in firma calculata in ani cu virgula 
- c este o constanta data de la tastatura (100) 
Sa se afiseze: 
- numele angajatului 
- denumirea departamentul in care lucreaza angajatul 
- data angajarii pentru angajat - afisati doar luna si anul 
- prima 
- numele sefului 
- denumirea departamentul sefului 
- data angajarii pentru sef - afisati doar luna si anul 
Rotunjiti prima la 2 zecimale 
Formatati numelui angajatilor si denumirea departamentele astfel incat sa apara prima 
litera mare si restul literelor mici. 
Ordonati crescator dupa nume. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 

Metoda 1: INNER JOIN


define n = '(months_between(sysdate, e.hiredate) / 12)'
select INITCAP(e.ename) "Nume_Ang",
INITCAP(d.dname) "Dep_Ang",
TO_CHAR(TO_DATE(e.hiredate,'dd/mm/yy'),'mm-yy') "Data_Ang",
ROUND(e.sal * &c * abs(log(2, &n) / ((power(&n, 2) + 1) *
sin(power(&n, 2) + 1))), 2) "Prima",
INITCAP(m.ename) "Sef",
INITCAP(dm.dname) "Dep_Sef",
TO_CHAR(TO_DATE(m.hiredate,'dd/mm/yy'),'mm-yy') "Data_Ang_Sef"
FROM emp e
INNER JOIN emp m
on e.mgr = m.empno
INNER JOIN dept d
on e.deptno = d.deptno
INNER JOIN dept dm
on m.deptno = dm.deptno
where length(e.ename) <= 5 and
EXTRACT(YEAR from e.hiredate) = EXTRACT(YEAR from m.hiredate)
order by 1 asc;

Metoda 2: LEFT OUTER JOIN


define n = '(months_between(sysdate, e.hiredate) / 12)'
select INITCAP(e.ename) "Nume_Ang",
INITCAP(d.dname) "Dep_Ang",
TO_CHAR(TO_DATE(e.hiredate,'dd/mm/yy'),'mm-yy') "Data_Ang",
ROUND(e.sal * &c * abs(log(2, &n) / ((power(&n, 2) + 1) *
sin(power(&n, 2) + 1))), 2) "Prima",
INITCAP(m.ename) "Sef",
INITCAP(dm.dname) "Dep_Sef",
TO_CHAR(TO_DATE(m.hiredate,'dd/mm/yy'),'mm-yy') "Data_Ang_Sef"
FROM emp e
LEFT OUTER JOIN emp m
on e.mgr = m.empno
LEFT OUTER JOIN dept d
on e.deptno = d.deptno
LEFT OUTER JOIN dept dm
on m.deptno = dm.deptno
where length(e.ename) <= 5 and
EXTRACT(YEAR from e.hiredate) = EXTRACT(YEAR from m.hiredate)
order by 1 asc;
Listati angajatii care s-au angajat in a doua jumatate a anului, au numele care incepe cu 'C' sau
'S' si s-au angajat cu cel
putin 8 luni inaintea sefului lor. Se va afisa si o prima calculata dupa formula
lg(salariu)^(sqrt(vechime in ani nerotunjita)). Antetul listei este angajat, data_ang, data_sef,
prima.
Obs: lg este logaritm in baza 10
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL.
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE.

Metoda1:
select
a1.ename angajat,
a1.hiredate,
a2.ename sef,
a2.hiredate,
(sysdate - a1.hiredate) / 365 vechime,
POWER(LOG(10, a1.sal), SQRT((sysdate - a1.hiredate) / 365)) prima
from
emp a1
inner join emp a2
on a1.mgr = a2.empno
where
(a1.ename like 'C%'
or a1.ename like 'S%')
and MONTHS_BETWEEN(a2.hiredate, a1.hiredate) >= 8;

Metoda2:
select
e1.ename "angajat",
e1.hiredate "data_ang",
e2.hiredate "data_sef",
(power(log(10, e1.sal), sqrt(months_between(sysdate, e1.hiredate) / 12))) "prima"
from emp e1
inner join emp e2
on e1.mgr = e2.empno and (months_between(e1.hiredate, e2.hiredate) >= 8)
where
(substr(e1.ename, 1, 1) like 'C' or substr(e1.ename, 1, 1) like 'S')
and extract(month from e1.hiredate) between 7 and 12;

Lab7
Afisati, pentru toti angajatii din tabela emp/angajati:
- anul angajarii in format YYYY (de exemplu: 2020) daca salariul lor este mai mare decat al
superiorului direct,
- luna in care s-au angajat in format string daca au salariul mai mic decat al superiorului direct
- ziua in care s-au angajat (exemplu: 15) daca au salariul egal cu al superiorului direct.
Antetul listei va fi urmatorul:
Nume_ang, Nume_sef, Salariu, Salariu_Sef, Calcul.
Ordonati dupa coloana calculata. Hint: folositi functia SIGN.
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

Metoda 1 (cu sign): (l-am inclus si pe president King aici)


select
e1.ename "Nume_ang",
m1.ename "Nume_sef",
e1.sal "Salariu",
m1.sal "Salariu_Sef",
case when SIGN(e1.sal - m1.sal) = 1 then to_char(e1.hiredate, 'YYYY')
when SIGN(e1.sal - m1.sal) = 0 then to_char(extract(day from e1.hiredate))
when SIGN(e1.sal - m1.sal) = -1 then to_char(e1.hiredate, 'MONTH')
end "Calcul"
from emp e1 left join emp m1 on e1.mgr = m1.empno
order by "Calcul";

Metoda 2 (fara sign): (fara president King)


select
e.ename "Nume_ang",
m.ename "Nume_sef",
e.sal "Salariu",
m.sal "Salariu_sef",
case when e.sal > m.sal then to_char(e.hiredate, 'YYYY')
when e.sal < m.sal then to_char(e.hiredate, 'MONTH')
else to_char(extract(day from e.hiredate))
end "Calcul"
from emp e join emp m on m.empno = e.mgr
order by "Calcul";

Sa se faca o lista cu numarul de subalterni care nu au functia 'MANAGER' si media veniturilor


acestora (al subalternitor) grupate dupa numele functiei si numele sefului lor.

Sa se afiseze doar liniile unde numarul de sublaterni este mai mare sau egala cu 2.
Lista are urmatorul antet

- Nume sef,

- Numele functiei subalternilor

- Numar subalterni care nu au functia 'MANAGER'

- Media veniturilot sublaternilor care nu au functia 'MANAGER'

Ordonati descrescator dupa numele sefului.

Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

SELECT
a1.ename Nume_sef,
a2.job Nume_functie_subalterni,
count(a2.ename) Numar_subalterni_care_nu_sunt_MANAGER,
avg (a2.sal + nvl(a2.comm, 0)) Medie_venituri_subalterni_care_nu_sunt_MANAGER
FROM
emp a2
INNER JOIN emp a1
ON a2.mgr = a1.empno AND a2.job != 'MANAGER'
HAVING
count(a2.ename) >= 2
GROUP BY a2.job, a1.ename
ORDER BY 1 DESC

Să se facă o listă cu: 


- departamentul (numele) 
- daca exista un sef (o persoana cu subordonati ince acest departament) 
- numarul de persoane din acel departament 
- numarul de grile salariale distincte pentru angajatii din departament 
- salariu minim/mediu/maxim pt angajatii din departament 
NOTE: 
- O SINGURA clauza, o SINGURA metoda. 
- Pentru Medie Rounjiti la 2 zecimale 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
SELECT
d.dname Denumire_Departament,
CASE COUNT(b.job)
WHEN 0 THEN 'NU'
ELSE 'DA'
END Exista_sef,
COUNT(e.deptno) Numar_angajati,
COUNT(DISTINCT g.grade) Grile_sal,
MIN(e.sal) Sal_minim,
ROUND(AVG(e.sal), 2) Sal_mediu,
MAX(e.sal) Sal_maxim
FROM
emp e
JOIN emp b
ON e.mgr = b.empno(+)
JOIN dept d
ON e.deptno = d.deptno
JOIN salgrade g
ON e.sal BETWEEN g.losal AND g.hisal
GROUP BY d.dname;

Să se facă o listă cu: 


- functia 
- daca exista un sef (o persoana cu subordonati cu aceasta functie) 
- numarul de persoane cu aceasta functie 
- numarul de grile salariale distincte pentru acea functie 
- salariu minim/mediu/maxim pt aceasta functie 
NOTE: 
- O SINGURA clauza, o SINGURA metoda. 
- Pentru Medie Rounjiti la 2 zecimale 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE 
 
select 
e.job functie, 
case count(b.job) 
when 0 then 'nu' 
else 'da' 
end exista_sef, 
count(e.job) nr_ang, 
count(distinct g.grade) nr_grile_sal_d, 
min(e.sal) sal_min, 
round(avg(e.sal), 2) sal_mediu, 
max(e.sal) sal_max 
from 
emp e 
join emp b 
on e.mgr = b.empno(+) 
join salgrade g 
on e.sal between g.losal and g.hisal 
group by 
e.job; 
 

Sa se afiseze angajatii care s-au angajat in prima jumatate a anului si cu cel putin 6 luni 
inaintea sefului lor. Se vor afisa numele angajatului, salariul si numele departamentului in 
care lucreaza angajatul. 
Lista va fi ordonata in functie de un caracter ce va fi citit de la tastatura, astfel: 
- daca caracterul citit e 'n' va fi ordonata dupa nume 
- daca caracterul citit e 's' va fi ordonata dupa salariu 
- daca caracterul citit este 'd' va fi ordonata dupa denumirea departamentului 
Lista are antetul: nume, salariu, departament. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

SELECT e.ename "nume",


e.sal "salariu",
d.dname "departament"
FROM emp e
INNER JOIN dept d
ON e.deptno = d.deptno
INNER JOIN emp m
ON e.mgr = m.empno
WHERE to_number (to_char (e.hiredate, 'MM')) <= 6
AND months_between(m.hiredate, e.hiredate) >= 6
ORDER BY(CASE WHEN '&&c' = 'n' THEN e.ename
WHEN '&c' = 's' THEN to_char(e.sal)
WHEN '&c' = 'd' THEN d.dname
END);
undefine c
Am folosit && pentru a citi o singura data de la tastatura caracterul c.

Lab8
Sa se afiseze, pentru fiecare angajat care face parte dintr-un departament cu cel putin 4
angajati si care are un venit peste
media veniturilor din firma, daca castiga mai mult decat seful sau direct (DA sau NU).
Se va afisa o lista cu antetul :
Angajatul, Departamentul, Venit angajat, Mai mult decat sef
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.
din rezolvarea asta nu lipseste conditia cu venit peste media veniturilor?
SELECT
e.ename "Angajatul",
d.dname "Departamentul",
e.sal + nvl(e.comm, 0) "Venit angajat",
CASE WHEN e.sal <= (SELECT e1.sal FROM emp e1 WHERE e1.empno = e.mgr)
THEN 'NU'
ELSE 'DA'
END
"Mai mult decat sef"
FROM emp e JOIN dept d ON e.deptno = d.deptno
WHERE
(SELECT COUNT(*) FROM emp e WHERE e.deptno = d.deptno) >= 4
AND e.sal+nvl(e.comm, 0) > (select avg(sal+nvl(comm, 0)) from emp);

Sa se scrie o singura cerere care afiseaza o lista cu:

- Numele angajatului (Nume_Angajat)

- Numele sefului (Nume_Sef)

- Grila salariala (Grad salarial) a angajatului (Grila_Angajat)

- Prima angajatului (Prima_Angajat)

Prima se calculeaza dupa urmatoarea formula:

- daca angajatul are salariul peste media pe departamentul lui: prima=Grila_Angajat * Salariu

- altfel, prima= Grila_Angajat * (venit sef)

Observatii:
- Rotunjiti primele angajatilor

- King nu are Sef

Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

SELECT
a1.ename Nume_Angajat,
a2.ename Nume_Sef,
s1.grade Grila_Angajat,
ROUND(CASE
WHEN a1.sal > ( SELECT AVG(sal)
FROM emp
WHERE deptno = a1.deptno )
THEN s1.grade * a1.sal
ELSE s1.grade * (a2.sal + (nvl(a2.comm, 0)))
END) Prima_Angajat
FROM
emp a1
LEFT OUTER JOIN emp a2
ON a1.mgr = a2.empno
INNER JOIN salgrade s1
ON a1.sal BETWEEN s1.losal AND s1.hisal;

Sa se acorde o bonificatie tuturor angajatilor care au salariul mai mare decit salariul mediu 
in departamentul in care lucreaza presedintele. Bonificatia reprezinta 25% din diferenta intre 
salariul angajatului si salariul mediu pe companie, rotunjita la doua zecimale. 
Lista are antetul nume, functie, salariu, bonificatie si va fi ordonata crescator dupa salariu si 
nume. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
select ename "nume", job "functie", sal "salariu",
ROUND((sal - (select avg(sal) from emp)) * 0.25, 2) "bonificatie"
from emp
where sal >
(select avg(sal) from emp where deptno =
(select deptno from emp where job like 'PRESIDENT'))
order by 3, 1;
Sa se afiseze angajatii care nu lucreaza in orasele DALLAS si CHICAGO si s-au angajat 
inaintea sefului lor direct cu cel putin 4 luni. Se va afisa numele angajatilor, salariul 
acestora, orasul unde lucreaza, numele sefului direct si salariul sefului direct. 
Lista are antetul nume, salariu, locatie, sef, salariu_sef. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

select
a.ename nume,
a.sal salariu,
d.loc locatie,
b.ename sef,
b.sal salariu_sef

from emp a
inner join emp b
on a.mgr = b.empno

inner join dept d


on a.deptno = d.deptno

where
months_between(b.hiredate, a.hiredate) >= 4 and
d.loc in (select loc from dept where loc not in ('DALLAS', 'CHICAGO'));

Metoda2:
select
e1.ename nume,
e1.sal salariu,
d1.loc locatie,
e2.ename sef,
e2.sal salariu_sef
from
emp e1 natural join dept d1
inner join emp e2
on e1.mgr = e2.empno
where
months_between(e2.hiredate, e1.hiredate) >= 4 and
d1.loc not in (select loc
from dept
where loc = 'DALLAS' or loc = 'CHICAGO');
Sa se afiseze angajatii care nu lucreaza in orasele DALLAS si CHICAGO si s-au angajat 
inaintea sefului lor direct cu cel putin 4 luni. Se va afisa numele angajatilor, salariul 
acestora, orasul unde lucreaza, numele sefului direct si salariul sefului direct. 
Lista are antetul nume, salariu, locatie, sef, salariu_sef. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

select e.ename "nume",


e.sal "salariu",
d.loc "locatie",
m.ename "sef",
m.sal "salariu_sef"
from emp e
inner join emp m
on e.mgr = m.empno
inner join dept d
on e.deptno = d.deptno
where months_between(m.hiredate, e.hiredate) >= 4 and
d.loc in (select loc from dept where UPPER(loc) not in ('DALLAS', 'CHICAGO'));

Alta Varianta:
SELECT
e1.ename Nume,
e1.sal Salariu,
d1.loc Locatie,
e2.ename Sef,
e2.sal Salariu_sef
FROM
emp e1 NATURAL JOIN dept d1
INNER JOIN emp e2
ON e1.mgr = e2.empno
WHERE
months_between(e2.hiredate, e1.hiredate) >= 4 AND
d1.loc NOT IN (SELECT loc FROM dept WHERE loc = 'DALLAS' OR loc = 'CHICAGO');
Lab9
Sa se creeze o tabela, denumita PRIMII_VENITI cu toti angajatii care au venit in firma primii 
din departamentul lor. Structura tabelei este urmatoarea : 
Nume_angajat, Den_departament, Data_angajare, Ani_vechime 
Se vor lua in considerare doar departamentele unde primii veniti au o vechime de cel putin 
39 de ani. 
Vechimea se va calcula ca si numar natural. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 
drop table PRIMII_VENITI;

create table PRIMII_VENITI


(
Nume_angajat,
Den_departament,
Data_angajare,
Ani_vechime
)
as
select e.ename "Nume_angajat",
d.dname "Den_departament",
e.hiredate "Data_angajare",
ROUND(months_between(sysdate, e.hiredate)/12) "Ani_vechime"
from emp e
inner join dept d
on e.deptno = d.deptno
where
ROUND(months_between(sysdate, e.hiredate)/12) >= 39 and
e.hiredate = (select MIN(hiredate)
from emp
group by deptno
having deptno = e.deptno);

select * from PRIMII_VENITI;

2. LAB6 
Sa se selecteze angajatii care au litera L in interiorul numelui, afisind numele angajatului 
intre caracterul '*', vechimea in ani rotunjita la intreg, salariul formatat la un sir de 10 
caractere, umplut dinspre stinga cu caracterul '$' (de ex. daca salariul e 1500 -> 
$$$$$$1500), precum si o prima calculata ca fiind 5^(sqrt(vechime in ani nerotunjita)). Lista 
are antetul nume, vechime, salariu, prima si e ordonata crescator dupa prima. 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 
Un exemplu de inregistrare din output este: 
COD  VENIT  Venit($) 
------------ ----------  ------------ 
KIN  60000 $$$$$$ 
-- metoda 1
SELECT
'* '||ename||' *' "nume",
ROUND(MONTHS_BETWEEN(sysdate, hiredate) / 12, 0) "vechime",
LPAD(sal, 10, '$') "salariu",
POWER(5, SQRT(MONTHS_BETWEEN(sysdate, hiredate) / 12)) "prima"
FROM emp
WHERE
ename LIKE '%L%'
ORDER BY 4;

-- metoda 2
SELECT
CONCAT(CONCAT('*', ename), '*') "nume",
ROUND(MONTHS_BETWEEN(sysdate, hiredate) / 12, 0) "vechime",
LPAD(sal, 10, '$') "salariu",
POWER(5, SQRT(MONTHS_BETWEEN(sysdate, hiredate) / 12)) "prima"
FROM emp
WHERE
ename LIKE '%L%'
ORDER BY "prima";

3 LAB5.
Creati scriptul Oracle SQL pentru rezolvarea urmatoarei cerinte, utilizand metode de JOIN: 
Să se selecteze, pentru fiecare angajat ce nu castiga niciun comision si care a venit in firma 
dupa 1 ianuarie 1981: numele angajatului, denumirea departamentului din care face parte, 
data angajarii, salariul său si numă rul gradului (plafonului) său salarial. Nu se va afisa 
angajatul FORD. Se se rezolve folosind doua metode distincte de join. 
METODA 1:

SELECT
e.ename,
d.dname,
e.hiredate,
e.sal,
s.grade
FROM emp e
JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal
JOIN dept d
ON e.deptno = d.deptno
WHERE
NVL(e.comm , 0) = 0
AND e.hiredate > '1-Jan-81'
AND e.ename != 'FORD';

METODA 2:

SELECT
e.ename,
d.dname,
e.hiredate,
e.sal,
s.grade
FROM
emp e,
salgrade s,
dept d
WHERE
e.sal BETWEEN s.losal AND s.hisal
AND e.deptno = d.deptno
AND NVL(e.comm , 0) = 0
AND e.hiredate > '1-Jan-81'
AND UPPER(e.ename) != 'FORD';

METODA3 CU 2 TIPURI DE JOIN:

SELECT
e.ename,
d.dname,
e.hiredate,
e.sal,
s.grade
FROM emp e
JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal
INNER JOIN dept d
ON e.deptno = d.deptno
WHERE
NVL(e.comm,0) = 0
AND e.hiredate > '1-Jan-81'
AND e.ename != 'FORD';

4. LAB7
Sa se afiseze angajatii care s-au angajat in prima jumatate a anului si cu cel putin 6 luni 
inaintea sefului lor. Se vor afisa numele angajatului, salariul si numele departamentului in 
care lucreaza angajatul. 
Lista va fi ordonata in functie de un caracter ce va fi citit de la tastatura, astfel: 
- daca caracterul citit e 'n' va fi ordonata dupa nume 
- daca caracterul citit e 's' va fi ordonata dupa salariu 
- daca caracterul citit este 'd' va fi ordonata dupa denumirea departamentului 
Lista are antetul: nume, salariu, departament. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

--metoda 1 cu decode
SELECT e.ename "nume",
e.sal "salariu",
d.dname "departament"
FROM emp e
JOIN dept d
ON e.deptno = d.deptno
LEFT JOIN emp mgr
ON e.mgr = mgr.empno
WHERE extract(month from e.hiredate) <= 6
AND ADD_MONTHS(e.hiredate, 6) <= mgr.hiredate
ORDER BY
(DECODE ('&caracter','n', e.ename,
's', TO_CHAR(e.sal),
'd', d.dname));
undefine caracter

-- metoda 2 cu case
SELECT e.ename "nume",
e.sal "salariu",
d.dname "departament"
FROM emp e
JOIN dept d
ON e.deptno = d.deptno
LEFT JOIN emp mgr
ON e.mgr = mgr.empno
WHERE extract(month from e.hiredate) <= 6
AND ADD_MONTHS(e.hiredate, 6) <= mgr.hiredate
ORDER BY (CASE
WHEN '&&caracter' = 'n' THEN e.ename
WHEN '&caracter' = 's' THEN TO_CHAR(e.sal)
WHEN '&caracter' = 'd' THEN d.dname
END);
undefine caracter

-- metoda 3 - case fara join

define c = &c

SELECT e.ename "Nume",


e.sal "Salariu",
d.dname "Departament"
FROM emp e, emp m, dept d
WHERE e.deptno = d.deptno and
e.mgr = m.empno and
extract(MONTH from e.hiredate) <= 6 and
add_months(e.hiredate, 6) <= m.hiredate
ORDER BY (CASE WHEN '&c' = 'n' THEN e.ename
WHEN '&c' = 's' THEN to_char(e.sal)
WHEN '&c' = 'd' THEN d.dname END);
undefine c

5. LAB8
Sa se calculeze, pentru fiecare angajat ce are, in departamentul sau, cel putin doi angajati 
cu un salariu mai mic decat el si care a venit in firma dupa seful sau direct: vechimea in ani 
(valoare intreaga), gradul salarial si diferenta dintre salariul sefului sau si salariul sau. 
Antetul listei de afisat trebuie sa fie : 
Nume angajat, Denumire departament, Ani vechime, Grad, Diferenta salariu sef  
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
SELECT
employee.ename "Nume angajat",
d.dname "Denumire departament",
extract(year from sysdate) - extract(year from employee.hiredate) "Ani vechime",
g.grade "Grad",
boss.sal - employee.sal "Diferenta salariu sef"
FROM
emp employee
JOIN dept d
on d.deptno = employee.deptno
JOIN emp boss
on boss.empno = employee.mgr
JOIN salgrade g
on employee.sal between g.losal and g.hisal
WHERE
(SELECT count(*)
FROM
emp e1
WHERE
e1.deptno = employee.deptno and employee.sal > e1.sal) >= 2
AND
employee.hiredate > boss.hiredate;

6. LAB6
Sa se scrie o cerere SQL care face o lista cu angajatii care au o vechime in firma mai mare 
de un an. Pentru fiecare angajat se vor afisa: Numele angajatului, ultima litera din numele 
lui, ziua in care s-a angajat acesta, vechimea lui in luni si numele departamenului urmat de 3 
*. Ordonati lista dupa vechime. 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 
Metoda 1.

SELECT
e1.ename Nume,
SUBSTR(e1.ename, LENGTH(e1.ename)) Ultima_litera,
EXTRACT(DAY from e1.hiredate) Zi_angajare,
TRUNC(MONTHS_BETWEEN(SYSDATE, e1.hiredate)) Vechime,
CONCAT(d1.dname, '***') Nume_departament
FROM
emp e1
INNER JOIN dept d1
ON e1.deptno = d1.deptno
WHERE
TRUNC(MONTHS_BETWEEN(SYSDATE, e1.hiredate)) / 12 > 1
ORDER BY Vechime;

Metoda 2.

SELECT
e1.ename Nume,
SUBSTR(e1.ename, LENGTH(e1.ename)) Ultima_litera,
EXTRACT(DAY from e1.hiredate) Zi_angajare,
TRUNC(MONTHS_BETWEEN(SYSDATE, e1.hiredate)) Vechime,
LPAD('***', LENGTH(d1.dname) + 3, d1.dname) Nume_departament
FROM
emp e1
RIGHT OUTER JOIN dept d1
ON e1.deptno = d1.deptno
WHERE
TRUNC(MONTHS_BETWEEN(SYSDATE, e1.hiredate) / 12) > 1
ORDER BY Vechime;

7. LAB7
Sa se afiseze, pentru toti angajatii departamentului RESEARCH, o lista care sa contina o 
apreciere a vechimii angajatului precum si numarul de subordonati direct ai angajatului 
respectiv. 
Aprecierea vechimii se va face astfel : 
- Daca au venit in firma inainte de 31 decembrie 1980, atunci vechime=’FOARTE VECHI’ 
- Daca au venit in firma intre anii 1981 si 1986, atunci vechime=’VECHI’ 
- Daca au venit in firma dupa 1986, atunci vechime=’RECENT’ 
Lista va afisa si angajatii care nu au subordonati. 
Antetul listei este urmatorul: 
Nume_angajat, Salariu, Apreciere_vechime, Nr_subordonati 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
 
SELECT
e1.ename as "Nume_angajat",
e1.sal as "Salariu",
CASE
WHEN e1.hiredate < '31-DEC-80' THEN 'FOARTE_VECHI'
WHEN extract(YEAR from e1.hiredate) >= 1981 AND extract(YEAR from e1.hiredate) <=
1986
THEN 'VECHI'
WHEN extract(YEAR from e1.hiredate) > 1986 THEN 'RECENT'
END as "Apreciere_vechime",
count(e2.ename) as "Nr_subordonati"
FROM emp e1
LEFT JOIN emp e2
ON e1.empno = e2.mgr
INNER JOIN dept d1
ON e1.deptno = d1.deptno AND d1.dname like 'RESEARCH'
GROUP BY
e1.ename, e1.sal, e1.hiredate;
 
8. LAB8
Sa se scrie o singura cerere care afiseaza o lista cu: 
- Numele angajatului (Nume_Angajat) 
- Numele sefului (Nume_Sef) 
- Grila salariala (Grad salarial) a angajatului (Grila_Angajat) 
- Prima angajatului (Prima_Angajat) 
Prima se calculeaza dupa urmatoarea formula: 
- daca angajatul are salariul peste media pe departamentul lui: prima=Grila_Angajat * 
Salariu 
- altfel, prima= Grila_Angajat * (venit sef) 
Observatii: 
- Rotunjiti primele angajatilor 
- King nu are Sef 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

SELECT
e1.ename as "Nume_Angajat",
e2.ename as "Nume_Sef",
s1.grade as "Grila_Angajat",
ROUND (CASE
WHEN e1.sal > (SELECT AVG(sal) FROM emp where deptno = e1.deptno)
THEN s1.grade * e1.sal
ELSE s1.grade * (e2.sal + nvl(e2.comm, 0))
END) as "Prima_angajat"
FROM emp e1
INNER JOIN salgrade s1
ON e1.sal BETWEEN s1.losal AND s1.hisal
LEFT OUTER JOIN emp e2
ON e1.mgr = e2.empno;

9. LAB6

Sa se calculeze o prima pentru angajatii care 


- au lungimea numelui mai mare sau egal cu 5 
- au venit in firma cu cel putin 6 luni in urma seful lor. 
Prima se calculeaza dupa urmatoarea formula: salariu * c * |ln(n)/((n^3-2)*cos(n^3-2))| unde 
- n este vechimea in firma calculata in ani cu virgula 
- c este o constanta data de la tastatura (100) 
Sa se afiseze: 
- numele angajatului 
- numele departamentul in care lucreaza angajatul 
- data angajarii pentru angajat - afisati doar luna si anul 
- prima 
- numele sefului 
- numele departamentul sefului 
- data angajarii pentru sef - afisati doar luna si anul 
Rotunjiti prima la 2 zecimale. 
Formatati numelui angajatilor si denumirea departamentele astfel incat sa apara prima 
litera mare si restul literelor mici. 
Ordonati crescator dupa nume. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 

Prima metoda:
SELECT
INITCAP(e.ename) "Nume_ang",
INITCAP(de.dname) "Den_dep",
TO_CHAR(e.hiredate, 'MM-YYYY') "Data_ang",
ROUND(e.sal * &c * ABS(LN(MONTHS_BETWEEN(SYSDATE, e.hiredate) / 12)
/ (POWER(MONTHS_BETWEEN(SYSDATE, e.hiredate) / 12, 3) - 2)
* COS(POWER(MONTHS_BETWEEN(SYSDATE, e.hiredate) / 12, 3) - 2)),
2) "Prima",
INITCAP(m.ename) "Nume_sef",
INITCAP(dm.dname) "Den_dep_sef",
TO_CHAR(m.hiredate, 'MM-YYYY') "Data_ang_sef"
FROM
emp e, dept de, emp m, dept dm
WHERE
e.mgr = m.empno AND
e.deptno = de.deptno AND
m.deptno = dm.deptno AND
LENGTH(e.ename) >= 5 AND
MONTHS_BETWEEN(e.hiredate, m.hiredate) >= 6
ORDER BY
e.ename;

A doua metoda:
SELECT
INITCAP(e.ename) "Nume_ang",
INITCAP(de.dname) "Den_dep",
TO_CHAR(e.hiredate, 'MM-YYYY') "Data_ang",
ROUND(e.sal * &c * ABS(LN(MONTHS_BETWEEN(SYSDATE, e.hiredate) / 12)
/ (POWER(MONTHS_BETWEEN(SYSDATE, e.hiredate) / 12, 3) - 2)
* COS(POWER(MONTHS_BETWEEN(SYSDATE, e.hiredate) / 12, 3) - 2)),
2) "Prima",
INITCAP(m.ename) "Nume_sef",
INITCAP(dm.dname) "Den_dep_sef",
TO_CHAR(m.hiredate, 'MM-YYYY') "Data_ang_sef"
FROM
emp e
JOIN dept de
ON e.deptno = de.deptno
INNER JOIN emp m
ON e.mgr = m.empno
INNER JOIN dept dm
ON m.deptno = dm.deptno
WHERE
LENGTH(e.ename) >= 5 AND
MONTHS_BETWEEN(e.hiredate, m.hiredate) >= 6
ORDER BY
e.ename;

10. LAB 8
Sa se scrie o cerere SQL care face o lista cu sefii de departament care primesc un bonus la 
salariu aplicand urmatoarele criterii: 
- sefii care au primit comision, primesc ca prima salariul mediu pe departamentul din care 
fac parte; 
- sefii care nu au primit comision primesc ca prima salariul minim pe departamentul din 
care fac parte. 
Antetul listei este urmatorul: 
Den_depart, Nume_ang, Comision, Sal_min_dep, Sal_mediu_dep, Prima 
Salariul mediu pe departament se afiseaza fara zecimale. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

column "Sal_mediu_dep" format 99999


select distinct
d.dname "Den_depart",
m.ename "Nume_ang",
m.comm "Comision",
(select min(sal) from emp dept_e where m.deptno = dept_e.deptno) "Sal_min_dep",
(select avg(sal) from emp dept_e where m.deptno = dept_e.deptno) "Sal_mediu_dep",
case when nvl(m.comm, 0) > 0 then (select avg(sal) from emp dept_e where m.deptno =
dept_e.deptno)
else (select min(sal) from emp dept_e where m.deptno = dept_e.deptno)
end "Prima"
from emp e, emp m, dept d
where
e.mgr = m.empno and
m.deptno = d.deptno and
m.job in ('MANAGER', 'PRESIDENT');

11. Lab4
Pentru toti angajatii care ((au venitul multiplu de 16) si (NU au venitul multiplu de 3)) sa se 
afiseze: 
- Nume_Angajat cu litere mici 
- Venit_Angajat 
- Departament: concatenarea cuvantului 'Dept' cu id-ul departamentului lor 
- Functie: Primele 3 litere din job, care are prima litera mare si restul mici 
Se vor prezenta doua scripturi (metode de rezolvare) diferite. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 
------metoda 1
select
lower(ename) as Nume_Angajat,
sal as Venit_Angajat,
'Dept'||deptno as Departament,
upper(substr(job, 0, 1)) || lower(substr(job, 1, 2)) as Functie
from emp
where (mod(sal, 16) = 0) and (mod(sal , 3) <> 0);

-----------metoda 2
select
lower(ename) 'Nume_Angajat',
sal 'Venit_Angajat',
concat('Dept', deptno) as 'Departament',
concat(upper(substr(job, 0, 1)), lower(substr(job, 1, 2))) 'Functie'
from emp
where not ((mod(sal, 16) <> 0) or (mod(sal , 3) = 0));
----------am negat la a doua varianta and-ul, folosind not si or

12. Lab5
Sa se faca o lista cu toti angajatii din firma, afisind numele, salariul si o coloana 
suplimentara numita RATE care ia valoarea 'Low' daca angajatul are o gradatie (grade) <3 si 
ia valoarea 'High' in caz contrar. Se vor afisa intai angajatii care au 'Low', urmati de cei care 
au 'High', ordonati apoi dupa salariu si dupa nume. Se se rezolve folosind doua metode 
distincte de join 
----------------------------------doar o metoda 
select 
a.ename, 
a.sal, 
'Low' as "Rate" 
from 
emp a 
inner join salgrade g 
on (a.sal between g.losal and g.hisal) and g.grade < 3 
union 
select 
a.ename, 
a.sal, 
'High' as "Rate" 
from 
emp a 
inner join salgrade g 
order byon3 (a.sal
DESC,between
2, 1; g.losal and g.hisal) and g.grade >= 3 

13. Lab6

Listati angajatii care s-au angajat in a doua jumatate a anului, au numele care incepe cu 'C' 
sau 'S' si s-au angajat cu cel putin 8 luni inaintea sefului lor. Se va afisa si o prima calculata 
dupa formula 
lg(salariu)^(sqrt(vechime in ani nerotunjita)). Antetul listei este angajat, data_ang, data_sef, 
prima. 
Obs: lg este logaritm in baza 10 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 
/*rezolvare 1*/

select
e1.ename "Nume",
e1.hiredate "Data_ang",
e2.hiredate "Data_ang_sef",
(power(log(10, e1.sal), sqrt(months_between(sysdate, e1.hiredate)/12))) "prima"
from emp e1
join emp e2
on e1.mgr = e2.empno and (months_between(e1.hiredate, e2.hiredate) >= 8)
where
(substr(e1.ename, 1, 1) like 'C' or substr(e1.ename, 1, 1) like 'S')
and extract(month from add_months(e1.hiredate, 6)) >= 1 and
extract(month from add_months(e1.hiredate, 6)) < 7;

/*rezolvare 2*/
select
e1.ename "Nume",
e1.hiredate "Data_ang",
e2.hiredate "Data_ang_sef",
(power (log(10, e1.sal), sqrt (months_between(sysdate, e1.hiredate)/12))) "Prima"
from emp e1
join emp e2
on e1.mgr = e2.empno and (months_between(e1.hiredate, e2.hiredate) >= 8)
where
(substr(e1.ename, 1, 1) like 'C' or substr(e1.ename, 1, 1) like 'S')
and extract(month from e1.hiredate) between 7 and 12;

14. Lab7

Să se facă o listă cu: 


- departamentul (numele) 
- daca exista un sef (o persoana cu subordonati ince acest departament) 
- numarul de persoane din acel departament 
- numarul de grile salariale distincte pentru angajatii din departament 
- salariu minim/mediu/maxim pt angajatii din departament 
NOTE: 
- O SINGURA clauza, o SINGURA metoda. 
- Pentru Medie Rounjiti la 2 zecimale 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
SELECT
d.dname Departament,
CASE COUNT(b.job)
WHEN 0 THEN 'NU'
ELSE 'DA'
END Exista_sef,
COUNT(e.deptno) Nr_ang,
COUNT(DISTINCT g.grade) Grile_sal,
MIN(e.sal) Sal_min,
ROUND(AVG(e.sal), 2) Sal_med,
MAX(e.sal) Sal_max
FROM
emp e
JOIN emp b
ON e.mgr = b.empno(+)
JOIN dept d
ON e.deptno = d.deptno
JOIN salgrade g
ON e.sal BETWEEN g.losal AND g.hisal
GROUP BY d.dname;

15. Lab5

Sa se scrie o cerere SQL care face o lista cu toti angajatii care au salariul mai mare decat 
jumatate din salariul sefului direct. Lista se ordoneaza dupa numele subalternilor si are 
urmatorul antet:  
Den_dep_subaltern Nume_subaltern Sal_subaltern Nume_sef Sal_sef 
Se se rezolve folosind doua metode distincte de join.
-- metoda 1
SELECT
den_dep "Den_dep_subaltern",
sub.nume "Nume_subaltern",
sub.salariu "Sal_subaltern",
sef.nume "Nume_sef",
sef.salariu "Sal_sef"
FROM
angajati sub
NATURAL JOIN departamente
INNER JOIN angajati sef
ON sub.id_sef = sef.id_ang
WHERE
sub.salariu > sef.salariu / 2
-- daca se ia in calcul si comisionul, atunci in loc de sub.salariu si
-- sef.salariu ar trebui sa fie (sub.salariu + nvl(sub.comision, 0)),
-- respectiv (sef.salariu + nvl(sef.comision, 0))
ORDER BY sub.nume;

-- metoda 2
SELECT
dsub.den_dep "Den_dep_subaltern",
sub.nume "Nume_subaltern",
sub.salariu "Sal_subaltern",
sef.nume "Nume_sef",
sef.salariu "Sal_sef"
FROM
angajati sub, angajati sef, departamente dsub
WHERE
dsub.id_dep = sub.id_dep AND
sub.id_sef = sef.id_ang AND
sub.salariu > sef.salariu / 2
-- daca se ia in calcul si comisionul, atunci in loc de sub.salariu si
-- sef.salariu ar trebui sa fie (sub.salariu + nvl(sub.comision, 0)),
-- respectiv (sef.salariu + nvl(sef.comision, 0))
ORDER BY 2;

-- metoda 3
SELECT
dsub.den_dep "Den_dep_subaltern",
sub.nume "Nume_subaltern",
sub.salariu "Sal_subaltern",
sef.nume "Nume_sef",
sef.salariu "Sal_sef"
FROM
angajati sub
INNER JOIN angajati sef
ON sub.id_sef = sef.id_ang
INNER JOIN departamente dsub
ON sub.id_dep = dsub.id_dep
WHERE
sub.salariu > sef.salariu / 2
-- daca se ia in calcul si comisionul, atunci in loc de sub.salariu si
-- sef.salariu ar trebui sa fie (sub.salariu + nvl(sub.comision, 0)),
-- respectiv (sef.salariu + nvl(sef.comision, 0))
ORDER BY sub.nume;

-- metoda 4
SELECT
dsub.den_dep "Den_dep_subaltern",
sub.nume "Nume_subaltern",
sub.salariu "Sal_subaltern",
sef.nume "Nume_sef",
sef.salariu "Sal_sef"
FROM
angajati sub
JOIN departamente dsub
USING (id_dep)
INNER JOIN angajati sef
ON sub.id_sef = sef.id_ang
WHERE
sub.salariu > sef.salariu / 2
-- daca se ia in calcul si comisionul, atunci in loc de sub.salariu si
-- sef.salariu ar trebui sa fie (sub.salariu + nvl(sub.comision, 0)),
-- respectiv (sef.salariu + nvl(sef.comision, 0))
ORDER BY sub.nume;

-- metoda 5
SELECT
dsub.den_dep "Den_dep_subaltern",
sub.nume "Nume_subaltern",
sub.salariu "Sal_subaltern",
sef.nume "Nume_sef",
sef.salariu "Sal_sef"
FROM
angajati sub, angajati sef, departamente dsub
WHERE
dsub.id_dep = sub.id_dep AND
sub.id_sef = sef.id_ang AND
sub.salariu > sef.salariu / 2
-- daca se ia in calcul si comisionul, atunci in loc de sub.salariu si
-- sef.salariu ar trebui sa fie (sub.salariu + nvl(sub.comision, 0)),
-- respectiv (sef.salariu + nvl(sef.comision, 0))
ORDER BY sub.nume;

-- metoda 6
SELECT
den_dep "Den_dep_subaltern",
sub.nume "Nume_subaltern",
sub.salariu "Sal_subaltern",
sef.nume "Nume_sef",
sef.salariu "Sal_sef"
FROM
angajati sub
NATURAL JOIN departamente
-- metoda aceasta ia in calcul si angajatii care nu au sef
LEFT OUTER JOIN angajati sef
ON sub.id_sef = sef.id_ang
AND sub.salariu > sef.salariu / 2
-- daca se ia in calcul si comisionul, atunci in loc de sub.salariu si
-- sef.salariu ar trebui sa fie (sub.salariu + nvl(sub.comision, 0)),
-- respectiv (sef.salariu + nvl(sef.comision, 0))
ORDER BY sub.nume;

16. Lab7

Sa se afiseze angajatii care s-au angajat in prima jumatate a anului si cu cel putin 6 luni 
inaintea sefului lor. Se vor afisa numele angajatului, salariul si numele departamentului in 
care lucreaza angajatul. 
Lista va fi ordonata in functie de un caracter ce va fi citit de la tastatura, astfel: 
- daca caracterul citit e 'n' va fi ordonata dupa nume 
- daca caracterul citit e 's' va fi ordonata dupa salariu 
- daca caracterul citit este 'd' va fi ordonata dupa denumirea departamentului 
Lista are antetul: nume, salariu, departament. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.
-- metoda 1 (am lasat doar salariul, daca se punea si comisionul ar fi fost (e.sal +
nvl(e.comm, 0))
SELECT e.ename "Nume",
e.sal "Salariu",
d.dname "Departament"
FROM emp e
JOIN dept d
ON e.deptno = d.deptno
LEFT JOIN emp mgr
ON e.mgr = mgr.empno
WHERE extract(month from e.hiredate) <= 6
AND ADD_MONTHS(e.hiredate, 6) <= mgr.hiredate
ORDER BY (DECODE ('&caracter','n', e.ename,
's', e.sal,
'd', d.dname));

-- metoda 2
SELECT e.ename "Nume",
e.sal "Salariu",
d.dname "Departament"
FROM emp e
JOIN dept d
ON e.deptno = d.deptno
LEFT JOIN emp mgr
ON e.mgr = mgr.empno
WHERE extract(month from e.hiredate) <= 6
AND MONTHS_BETWEEN(mgr.hiredate, e.hiredate) >= 6
ORDER BY (DECODE ('&caracter','n', e.ename,
's', e.sal,
'd', d.dname));

-- metoda 3
SELECT e.ename "Nume",
e.sal "Salariu",
d.dname "Departament"
FROM emp e
JOIN dept d
ON e.deptno = d.deptno
LEFT JOIN emp mgr
ON e.mgr = mgr.empno
WHERE extract(month from e.hiredate) <= 6
AND ADD_MONTHS(e.hiredate, 6) <= mgr.hiredate
ORDER BY (CASE
WHEN '&&caracter' = 'n' THEN e.ename
WHEN '&caracter' = 's' THEN TO_CHAR(e.sal)
WHEN '&caracter' = 'd' THEN d.dname
END);

undefine caracter
17. Lab8

Afisati angajatii al caror grad salarial se regaseste printre gradele salariale maxime ale 
angajatilor, pentru fiecare departament si an al angajarii. 
Hint: gruparea se face dupa departament si anul angajarii 
Antetul listei este urmatorul: Nume_angajat, Nume_departament, Grad_salarial, 
An_angajare. 
Sortati dupa numele departamentului si anul angajarii. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.
-- metoda 1
SELECT
e.ename "Nume_angajat",
d.dname "Nume_departament",
s.grade "Grad_salarial",
extract(year FROM e.hiredate) "An_angajare"
FROM
emp e
JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal
JOIN dept d
ON e.deptno = d.deptno
WHERE
(s.grade, d.deptno, extract(year from e.hiredate))
IN (SELECT MAX(sg.grade), dsub.deptno, extract(year from esub.hiredate)
FROM
salgrade sg
JOIN emp esub
ON esub.sal BETWEEN sg.losal AND sg.hisal
JOIN dept dsub
ON esub.deptno = dsub.deptno
GROUP BY dsub.deptno, extract(year from esub.hiredate))
ORDER BY 2, 4;

-- metoda 2
SELECT
e.ename "Nume_angajat",
d.dname "Nume_departament",
s.grade "Grad_salarial",
LPAD(TO_CHAR(e.hiredate, 'YYYY'), 10, ' ') "An_angajare"
FROM
emp e
INNER JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal
NATURAL JOIN dept d
WHERE
(s.grade, deptno, TO_CHAR(e.hiredate, 'YYYY'))
IN (SELECT MAX(sg.grade), deptno, TO_CHAR(esub.hiredate, 'YYYY')
FROM
salgrade sg
INNER JOIN emp esub
ON esub.sal BETWEEN sg.losal AND sg.hisal
NATURAL JOIN dept dsub
GROUP BY deptno, TO_CHAR(esub.hiredate, 'YYYY'))
ORDER BY d.dname, TO_CHAR(e.hiredate, 'YYYY');

LAB 4 recuperare
Pentru toti angajatii care ((au venitul multiplu de 16) si (NU au venitul multiplu de 3)) sa se 
afiseze: 
- Nume_Angajat cu litere mici 
- Venit_Angajat 
- Departament: concatenarea cuvantului 'Dept' cu id-ul departamentului lor 
- Functie: Primele 3 litere din job, care are prima litera mare si restul mici 
Se vor prezenta doua scripturi (metode de rezolvare) diferite. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 

Metoda 1
select
lower(a.ename) "Nume_Angajat",
sal + nvl(comm, 0) "Venit_Angajat",
concat('Dept',a.deptno) "Departament",
initcap(substr(a.job,0, 3)) "Functie"
from emp a
where MOD(a.sal + nvl(comm, 0), 16) = 0 and MOD(a.sal + nvl(comm, 0), 3) != 0;

Metoda 2
define venit='sal + nvl(comm, 0)'
select
lower(a.ename) "Nume_Angajat",
&venit "Venit_Angajat",
concat('Dept',a.deptno) "Departament",
initcap(substr(a.job,0, 3)) "Functie"
from emp a
where MOD(&venit, 16) = 0 and MOD(&venit, 3) != 0;
undefine venit
Acordati o prima angajatilor ale caror nume au lungime para sau care s-au angajat in firma 
in luna aprilie. Prima va fi c% din salariu altfel, unde c este o variabila introdusa de la 
tastatura. 
Antetul listei va contine: 
- numele angajatului, 
- data angajarii, 
- ultimele 3 litere din functia angajatului concatenate cu ultimele 3 litere din numele 
angajatului “Calcul Nume Functie”, 
- prima “Prima”. 
Cerinta trebuie rezolvata prin doua metode (scripturi) diferite. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 
-- Met 1
select
ename,
hiredate,
job,
substr(job, length(job) - 2)||''||
substr(ename, length(ename) - 2) as "Calcul Nume Functie",
(&c / 100 * sal) as "Prima"
from
emp
where
mod(length(ename), 2) = 0 or
hiredate like '%-APR-%';

-- Met 2
select
ename,
hiredate,
job,
concat(substr(job, length(job) - 2),
substr(ename, length(ename) - 2)) as "Calcul Nume Functie",
(&c / 100 * sal) as "Prima"
from
emp
where
mod(length(ename), 2) = 0 or
hiredate like '%-APR-%';

Selectati angajatii care s-au angajat in ultimele 4 luni ale anului, intre anii 1981 si 1983, nu 
primesc comision si lucreaza ca analisti . Se va afisa si data semnarii contractului de 
angajare, stiind ca aceasta a fost urmatoarea zi de luni dupa data angajarii. Se va afisa 
numele concatentat cu functia (ex. "FORD is ANALYST"), functia, salariul anual (concatenat 
cu sirul 'USD'), comisionul (daca e nul se va afisa 0), data semnarii contractului (in format cu 
luna si anul complet, ex.'24-DECEMBER-1982') si se va ordona alfabetic dupa nume. 
Antetul listei este nume_func, salariu_anual, comision, data_contract. 
Se vor prezenta doua scripturi (metode de rezolvare) diferite. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 
-- Metoda 1
SELECT ename||' is '||job nume_func, CONCAT(sal * 12, 'USD') salariu_anual, nvl(comm, 0) as
comision, to_char(next_day(hiredate, 'MONDAY'), 'DD-MONTH-YYYY') data_contract
FROM emp
WHERE to_number(to_char(hiredate, 'YYYY')) >= 1981 and to_number(to_char(hiredate,
'YYYY')) <= 1983
AND extract(MONTH from hiredate) > 8
AND nvl(comm, 0) = 0
AND job = 'ANALYST'
ORDER BY ename;

-- Metoda 2
SELECT ename||' is '||job nume_func, CONCAT(sal * 12, 'USD') salariu_anual, nvl(comm, 0) as
comision, to_char(next_day(hiredate, 'MONDAY'), 'DD-MONTH-YYYY') data_contract
FROM emp
WHERE extract(month from hiredate) >= 9
AND extract(year from hiredate) >= 1981
AND extract(year from hiredate) <= 1983
AND nvl(comm, 0) = 0
AND job = 'ANALYST'
ORDER BY ename;

Afisati, pentru angajatii care : (fac parte din departamentele 10 sau 20 si care s-au angajat 
dupa anul 1980) sau (a caror functie contine 5 caractere), urmatoarea lista: 
- numele, 
- functia, 
- data angajarii, 
- caracterul din mijlocul numelui lor “Caracter Mijloc”, 
- ultimele 3 caractere din functie “Ultimele 3”, 
- ultima zi din luna in care s-au angajat “Ultima Zi Luna”. 
Cerinta trebuie rezolvata prin doua metode (scripturi) diferite. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 

-- Metoda 1
SELECT
ename Nume,
job Functia,
hiredate Data_ang,
substr(ename, length(ename)/2 + 1, 1) Caracter_mijloc,
substr(job, length(job) - 2, 3) Ultimele_3,
extract(Day from last_day(hiredate)) Ultima_Zi_Luna
FROM
emp
WHERE
(deptno IN (10, 20) AND
hiredate > '01-JAN-1980') OR
length(job) = 5;

-- Metoda 2
SELECT
ename Nume,
job Functia,
hiredate Data_ang,
substr(ename, length(ename)/2 + 1, 1) Caracter_mijloc,
substr(job, length(job) - 2, 3) Ultimele_3,
extract(Day from last_day(hiredate)) Ultima_Zi_Luna
FROM
emp
WHERE
(deptno IN (10, 20) AND
extract(YEAR from hiredate) > 1980) OR
length(job) = 5;

Lab4 la final 
Lab 5 
Să se scriere o cerere SQL care face o listă cu toți angajații care au gradul de salarizare 
apropiat de cel al șefului lor(grad_salarizare_ang – grad_salarizare_sef<=1). Dacă angajatul 
nu are șef atunci conditia se considera indeplinita automat. Antetul listei este urmatorul: 
Nume_Angajat Nume_Sef Grila_Angajat Grila_Sef 
Se se rezolve folosind doua metode distincte de join. 

/*
select
a1.ename "Nume_angajat",
a2.ename "Nume_sef",
g1.grade "Grila_angajat",
g2.grade "Grila_sef"
from
emp a1
left outer join emp a2
on a1.mgr = a2.empno
left outer join salgrade g2
on a2.sal between g2.losal and g2.hisal
inner join salgrade g1
on (a1.sal between g1.losal and g1.hisal) and
(g2.grade - g1.grade <= 1 or g2.grade is null);
*/

select
a1.ename "Nume_angajat",
a2.ename "Nume_sef",
g1.grade "Grila_angajat",
g2.grade "Grila_sef"
from
salgrade g1, emp a1
left outer join emp a2
on a1.mgr = a2.empno
left outer join salgrade g2
on a2.sal between g2.losal and g2.hisal
where
(a1.sal between g1.losal and g1.hisal) and
(g2.grade - g1.grade <= 1 or g2.grade is null);
Sa se scrie o cerere SQL care face o lista cu toti angajatii care au salariul mai mare decat 
jumatate din salariul sefului direct. Lista se ordoneaza dupa numele subalternilor si are 
urmatorul antet:  
Den_dep_subaltern Nume_subaltern Sal_subaltern Nume_sef Sal_sef 
Se se rezolve folosind doua metode distincte de join. 
-- Metoda 1
select
d.dname "Nume departament",
e1.ename "Nume subaltern",
e1.sal "Salariu Subaltern",
e2.ename "Nume sef",
e2.sal "Salariu sef"
from
emp e1,
emp e2,
dept d
where
e1.sal > e2.sal / 2
and e1.mgr = e2.empno
and d.deptno = e1.deptno
order by 2;

-- Metoda 2
select
d.dname "Nume departament",
e1.ename "Nume subaltern",
e1.sal "Salariu Subaltern",
e2.ename "Nume sef",
e2.sal "Salariu sef"
from
emp e1
inner join emp e2 on e1.mgr = e2.empno
inner join dept d on d.deptno = e1.deptno
where
e1.sal > e2.sal / 2
order by 2;
LAB6
Pentru angajatii ce au aceeai paritate a lungimii numelui ca cea a sefului lor (daca nu au 
sef se considera ca indeplinesc aceasta conditie), faceti o lista cu: 
- numele departamentului lor si al celui in care este seful, scris cu litere mari si separate 
prin virgula (NUME_DEPT) 
- cate luni complete au lucrat in firma in care(LUNI_LUCRATE_ANG) 
- initiala numelui lor, ca litera mica (INITIALA_ANG) 
- ultima cifra a venitului lor (ULTIMA_CIFRA_SALARIU) 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 
/* select
concat(concat(upper(d1.dname), ', '), upper(d2.dname)) as "NUME_DEPT",
floor(months_between(e1.hiredate, e2.hiredate)) as
"LUNI_INAINTEA_SEFULUI",
lower(substr(e1.ename, 1, 1)) as "INITIALA_ANG",
mod(e1.sal, 10) as "Ultima_cifra_salariu"
from
dept d1, emp e1
left outer join emp e2
on e1.mgr = e2.empno
left outer join dept d2
on e2.deptno = d2.deptno
where
e1.deptno = d1. deptno and
(mod(length(e1.ename), 2) = mod(length(e2.ename), 2) or e1.mgr is null);
*/

select
upper(d1.dname)||', '||upper(d2.dname),
floor(months_between(e1.hiredate, e2.hiredate)) as
"LUNI_INAINTEA_SEFULUI",
lower(substr(e1.ename, 1, 1)) as "INITIALA_ANG",
mod(e1.sal, 10) as "Ultima_cifra_salariu"
from
emp e1
inner join dept d1
on e1.deptno = d1.deptno
left outer join emp e2
on e1.mgr = e2.empno
left outer join dept d2
on e2.deptno = d2.deptno
where
e1.deptno = d1. deptno and
(mod(length(e1.ename), 2) = mod(length(e2.ename), 2) or e1.mgr is null);

Sa se scrie o cerere SQL care face o lista cu toti angajatii care au venit in firma la o 
diferenta de cel putin 3 luni fata de seful lor. Cerintele de afisare sunt : 
- numele angajatului precedat de 3 * 
- numele sefului lor cu litere mici 
- prima zi din anul in care s-au angajat(ca data calendaristica) 
- a doua zi de marti din anul in care s-a angajat seful lor(ca data calendaristica) 
Antetul listei este urmatorul: 
Nume_ang, Nume_sef, Prima_zi_an, Data_zi_marti 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 
-- MET 1
select
concat('3 * ', a1.ename) as "Nume_ang",
lower(a2.ename) as "Nume_sef",
trunc(a1.hiredate, 'YEAR') as "Prima_zi_an",
next_day(next_day(trunc(a2.hiredate, 'YEAR'), 'TUESDAY'), 'TUESDAY')
as "Data_zi_marti"
from
emp a1,
emp a2
where
a1.mgr = a2.empno and
months_between(a2.hiredate, a1.hiredate) >= 3;

-- MET 2
select
concat('3 * ', a1.ename) as "Nume_ang",
lower(a2.ename) as "Nume_sef",
trunc(a1.hiredate, 'YEAR') as "Prima_zi_an",
next_day(next_day(trunc(a2.hiredate, 'YEAR'), 'TUESDAY'), 'TUESDAY')
as "Data_zi_marti"
from
emp a1
full outer join emp a2
on a1.mgr = a2.empno
where
months_between(a2.hiredate, a1.hiredate) >= 3;

Sa se scrie o cerere SQL care face o lista cu angajatii care au o vechime in firma mai mare 
de un an. Pentru fiecare angajat se vor afisa: Numele angajatului, ultima litera din numele 
lui, ziua in care s-a angajat acesta, vechimea lui in luni si numele departamenului urmat de 
3 *. Ordonati lista dupa vechime. 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 
-- metoda 1 inner join

select ename as nume,


substr(ename, length(ename)) as ultima_litera,
extract(day from hiredate) as ziua_ang,
trunc(months_between(sysdate, hiredate)) as vechime_luni,
concat(d.dname, '***') as nume_dep
from emp emp
inner join dept d
on emp.deptno = d.deptno
where trunc(months_between(sysdate, hiredate)) > 12 -- mai mult de 1 an
order by hiredate desc;
-- metoda 2 full outer join

select ename as nume,


substr(ename, length(ename)) as ultima_litera,
extract(day from hiredate) as ziua_ang,
trunc(months_between(sysdate, hiredate)) as vechime_luni,
concat(d.dname, '***') as nume_dep
from emp emp
full outer join dept d
on emp.deptno = d.deptno
where trunc(months_between(sysdate, hiredate)) > 12 -- mai mult de 1 an
order by hiredate desc;

Sa se selecteze angajatii care au litera L in interiorul numelui, afisind numele angajatului 


intre caracterul '*', vechimea in ani rotunjita la intreg, salariul formatat la un sir de 10 
caractere, umplut dinspre stinga cu caracterul '$' (de ex. daca salariul e 1500 -> 
$$$$$$1500), precum si o prima calculata ca fiind 5^(sqrt(vechime in ani nerotunjita)). 
Lista are antetul nume, vechime, salariu, prima si e ordonata crescator dupa prima. 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 
Un exemplu de inregistrare din output este: 
COD VENIT  Venit($) 
------------ ----------  ------------ 
KIN 60000  $$$$$$ 

-- Metoda 1
SELECT
CONCAT(CONCAT('*', ename), '*') NUME,
ROUND((SYSDATE - hiredate) / 365) VECHIME,
LPAD(sal, 10, '$') SALARIU,
POWER(5, SQRT((SYSDATE - hiredate) / 365)) PRIMA
FROM
emp
WHERE
INSTR(ename, 'L') != 0
ORDER BY PRIMA ASC;

-- Metoda 2
SELECT
CONCAT('*', CONCAT(ename, '*')) NUME,
ROUND(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) VECHIME,
LPAD(sal, 10, '$') SALARIU,
POWER(5, SQRT(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12)) PRIMA
FROM
emp
WHERE
INSTR(ename, 'L') != 0
ORDER BY PRIMA ASC;

LAB7
Sa se afiseze angajatii care s-au angajat in prima jumatate a anului si cu cel putin 6 luni 
inaintea sefului lor. Se vor afisa numele angajatului, salariul si numele departamentului in 
care lucreaza angajatul. 
Lista va fi ordonata in functie de un caracter ce va fi citit de la tastatura, astfel: 
- daca caracterul citit e 'n' va fi ordonata dupa nume 
- daca caracterul citit e 's' va fi ordonata dupa salariu 
- daca caracterul citit este 'd' va fi ordonata dupa denumirea departamentului 
Lista are antetul: nume, salariu, departament. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
select
ang.ename nume,
ang.sal salariu,
d.dname departament
from emp sef
join emp ang
on ang.mgr = sef.empno
join dept d
on ang.deptno = d.deptno
where to_number(to_char(ang.hiredate, 'MM')) <=6
and months_between(sef.hiredate, ang.hiredate) >= 6
order by
case
when &&c = 'n' then 1
when &c = 's' then 2
when &c = 'd' then 3
End;

Să se facă o listă cu: 


- functia 
- daca exista un sef (o persoana cu subordonati cu aceasta functie) 
- numarul de persoane cu aceasta functie 
- numarul de grile salariale distincte pentru acea functie 
- salariu minim/mediu/maxim pt aceasta functie 
NOTE: 
- O SINGURA clauza, o SINGURA metoda. 
- Pentru Medie Rounjiti la 2 zecimale 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE 
 
select distinct 
e1.job as "functie", 
(select count(e2.ename) from emp e2 where e1.job = e2.job) as "numar persoane", 
case  
when (select count(e3.mgr) from emp e3 where e3.mgr = e1.empno) = 0 then 
'No boss' 
else 'Boss' 
end "isBoss", 
(select count(distinct s1.grade) from emp e2, salgrade s1 
where e1.job = e2.job and 
s1.losal <= e2.sal and 
s1.hisal >= e2.sal) as "numar grile", 
(select min(e2.sal) from emp e2 where e1.job = e2.job) as "sal minim", 
round((select avg(e2.sal) from emp e2 where e1.job = e2.job), 2) as "sal mediu", 
(select max(e2.sal) from emp e2 where e1.job = e2.job) as "sal maxim" 
from emp e1 
order by e1.job; 
 
Afisati, pentru toti angajatii din tabela emp/angajati: 
- anul angajarii in format YYYY (de exemplu: 2020) daca salariul lor este mai mare decat al 
superiorului direct, 
- luna in care s-au angajat in format string daca au salariul mai mic decat al superiorului 
direct 
- ziua in care s-au angajat (exemplu: 15) daca au salariul egal cu al superiorului direct. 
Antetul listei va fi urmatorul: 
Nume_ang, Nume_sef, Salariu, Salariu_Sef, Calcul. 
Ordonati dupa coloana calculata. Hint: folositi functia SIGN. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

select e1.ename nume_ang, e2.ename nume_sef, e1.sal salariu, e2.sal salariu_sef,


case
when e1.sal > e2.sal then to_char(e1.hiredate, 'YYYY')
when e1.sal < e2.sal then to_char(e1.hiredate, 'mm')
else to_char(e1.hiredate, 'dd')
end calcul
from
emp e1,
emp e2
where e1.mgr = e2.empno
order by calcul;

LAB8
Sa se selecteze numele angajatului, numele departamentului in care lucreaza, functia si 
salariul, pentru angajatii care au salariul maxim pentru functia lor in departametul in care 
lucreaza. 
Ordonati dupa numele departamentului, functie si numele angajatului. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
select
a.ename "Nume Angajat",
d.dname "Nume departament",
a.job "Functie",
a.sal "Salariu"
from
emp a
join dept d
on d.deptno = a.deptno
where
a.sal =
(select max(e.sal)
from emp e
where a.deptno = e.deptno
and a.job = e.job)
order by
2,3,1;

Sa se afiseze, pentru fiecare angajat care face parte dintr-un departament cu cel putin 4 
angajati si care are un venit peste media veniturilor din firma, daca castiga mai mult decat 
seful sau direct (DA sau NU). 
Se va afisa o lista cu antetul : 
Angajatul, Departamentul, Venit angajat, Mai mult decat sef 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
select
ang.ename "Angajatul",
ang.deptno "Departamentul",
(ang.sal + nvl(ang.comm,0)) "Venit angajat"
,case
when (ang.sal + nvl(ang.comm,0)) > (sef.sal + nvl(sef.comm,0)) then 'DA'
else 'NU'
end "Mai mult decat sef"
from emp ang
join emp sef
on ang.mgr = sef.empno
where ang.deptno in (select deptno from emp group by deptno having count(empno) >= 4)
and (ang.sal + nvl(ang.comm,0)) > (select avg(sal + nvl(comm,0)) from emp);
Sa se acorde o bonificatie tuturor angajatilor care au salariul mai mare decit salariul mediu 
in departamentul in care lucreaza presedintele. Bonificatia reprezinta 25% din diferenta intre 
salariul angajatului si salariul mediu pe companie, rotunjita la doua zecimale. 
Lista are antetul nume, functie, salariu, bonificatie si va fi ordonata crescator dupa salariu si 
nume. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

select
e.ename "nume",
e.job "functie",
e.sal "salariu",
round(0.25*(e.sal - (select avg(sal) from emp)), 2) "bonificatie"
from
emp e
where
e.sal > (select
avg(sal)
from
emp
where
deptno = (select
deptno
from
emp
where
job like 'PRESIDENT'))
order by
e.sal, e.ename asc;

Sa se afiseze angajatii care nu lucreaza in orasele DALLAS si CHICAGO si s-au angajat 


inaintea sefului lor direct cu cel putin 4 luni. Se va afisa numele angajatilor, salariul 
acestora, orasul unde lucreaza, numele sefului direct si salariul sefului direct. 
Lista are antetul nume, salariu, locatie, sef, salariu_sef. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
select
e1.ename nume,
e1.sal salariu,
d1.loc locatie,
e2.ename sef,
e2.sal salariu_sef
from
emp e1
inner join emp e2
on e1.mgr = e2.empno
inner join dept d1
on e1.deptno = d1.deptno
where
months_between(e2.hiredate, e1.hiredate) >= 4 and
d1.loc not in (select loc from dept where
loc = 'DALLAS' or loc = 'CHICAGO');

LAB9

LAB10
Să se creeze tabela Statistica_Sefi, cu următoarele coloane: 
- Nume_Sef 
- Venit_Sef 
- Grila_Salariala_Subalterni (grila salarială a subalternilor pentru care el este șef) 
- Numar_Subalterni (numărul subalternilor pentru acest șef cu această grilă) 
- Medie_Venit_Subalterni (media veniturilor subalternilor cu acea grila salarială) 
Să se populeze tabela în conformitate cu aceste cerințe pentru fiecare șef din companie, 
persoană din tabela EMP care are minim un subaltern, care este din același departament cu 
minim un subaltern. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 
 
create table Statistica_Sefi 

Nume_Sef, 
Venit_Sef, 
Grila_Salariala_Subalterni, 
Numar_Subalterni, 
Medie_Venit_Subalterni 

as 
select distinct 
s.ename, 
s.sal, 
(select grade from salgrade where e.sal <= hisal and e.sal >= losal), 
(select count(*) from emp aux where aux.mgr = s.empno), 
(select avg(sal) from emp aux where aux.mgr = s.empno) 
from 
emp e, 
emp s 
where 
s.empno = e.mgr 
order by s.ename; 
 

Centralizare subiecte teste BD 332CA

TEST RECUPERARE LAB 4


1​.Afisati, pentru angajatii care : (fac parte din departamentele 10 sau 20 si care s-au angajat dupa
anul 1980) sau (a caror functie contine 5 caractere), urmatoarea lista:
- numele,
- functia,
- data angajarii,
- caracterul din mijlocul numelui lor “Caracter Mijloc”,
- ultimele 3 caractere din functie “Ultimele 3”,
- ultima zi din luna in care s-au angajat “Ultima Zi Luna”.
Cerinta trebuie rezolvata prin doua metode (scripturi) diferite.
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE.
REZOLVARE
select ename, job, hiredate,
SUBSTR(ename, LENGTH(ENAME) / 2 + 1, 1) "Caracter Mijloc",
SUBSTR(job, LENGTH(job)-3 +1, 3) "Ultimele 3",
LAST_DAY(hiredate) "Ultima Zi Luna"
from emp
where ((deptno=10 or deptno=20) and
EXTRACT(YEAR from hiredate)>=1980) or
LENGTH(job)=5;
select ename, job, hiredate,
SUBSTR(ename, LENGTH(ENAME) / 2 + 1, 1) "Caracter Mijloc",
SUBSTR(job, LENGTH(job)-3 +1, 3) "Ultimele 3",
LAST_DAY(hiredate) "Ultima Zi Luna"
from emp
where ((deptno in (10, 20)) and
hiredate>='1-JAN-1980') or
job LIKE '_____';

2. Pentru toti angajatii care ((au venitul multiplu de 16) si (NU au venitul multiplu de 3)) sa 
se afiseze: 
- Nume_Angajat cu litere mici 
- Venit_Angajat 
- Departament: concatenarea cuvantului 'Dept' cu id-ul departamentului lor 
- Functie: Primele 3 litere din job, care are prima litera mare si restul mici 
Se vor prezenta doua scripturi (metode de rezolvare) diferite. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 

VARIANTA 1:
select
lower(ename) "Nume_Angajat",
sal+nvl(comm, 0) "Venit_Angajat",
concat('Dept', to_char(deptno)) "Departament",
INITCAP(substr(job, 0, 3)) "Functie"
from
emp
where
mod((sal+nvl(comm,0)), 16) = 0 and
mod((sal+nvl(comm,0)), 3) != 0;

VARIANTA 2:
define venit = sal+nvl(comm,0);
select
lower(ename) "Nume_Angajat",
&venit "Venit_Angajat",
'Dept' || to_char(deptno) "Departament",
upper(substr(job, 0, 1)) || lower(substr(job, 2, 2)) "Functie"
from
emp
where
mod(&venit, 16) = 0 and
mod(&venit, 3) != 0;

3.Selectati angajatii care s-au angajat in ultimele 4 luni ale anului, intre anii 1981 si 1983, nu 
primesc comision si lucreaza ca analisti . Se va afisa si data semnarii contractului de 
angajare, stiind ca aceasta a fost urmatoarea zi de luni dupa data angajarii. Se va afisa 
numele concatentat cu functia (ex. "FORD is ANALYST"), functia, salariul anual (concatenat 
cu sirul 'USD'), comisionul (daca e nul se va afisa 0), data semnarii contractului (in format cu 
luna si anul complet, ex.'24-DECEMBER-1982') si se va ordona alfabetic dupa nume. 
Antetul listei este nume_func, salariu_anual, comision, data_contract. 
Se vor prezenta doua scripturi (metode de rezolvare) diferite. 
Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si SALGRADE. 
REZOLVARE
--- METODA 1 ---

select
concat(concat(ename, ' is '), job) "nume_func",
concat(to_char(sal * 12), 'USD') "salariu_anual",
nvl(comm, 0) "comision",
to_char(next_day(hiredate, 'MONDAY'), 'DD-MONTH-YYYY') "data_contract"
from
emp
where
to_number(to_char(hiredate, 'YYYY')) between 1981 and 1983
and
(comm is null or comm = 0)
and
to_number(to_char(hiredate, 'MM')) > 8
and
job like 'ANALYST'
order by ename;

--- METODA 2 ---

select
(ename || ' is ' || job) "nume_func",
((sal * 12) || 'USD') "salariu_anual",
nvl(comm, 0) "comision",
to_char(next_day(hiredate, 'MONDAY'), 'DD-MONTH-YYYY') "data_contract"
from
emp
where
to_number(to_char(hiredate, 'YYYY')) >= 1981 and to_number(to_char(hiredate,
'YYYY')) <= 1983
and
nvl(comm, 0) = 0
and
extract(MONTH from hiredate) > 8
and
job like 'ANALYST'
order by ename;

TEST LAB 5

1. Sa se scrie o cerere SQL care face o lista cu toti angajatii care au salariul mai mare decat
jumatate din salariul sefului direct. Lista se ordoneaza dupa numele subalternilor si are
urmatorul antet:

Den_dep_subaltern Nume_subaltern Sal_subaltern Nume_sef Sal_sef

Se se rezolve folosind doua metode distincte de join.

REZOLVARI
-- Metoda 1
select
d1.dname "Den_dep_subaltern",
a1.ename "Nume_subaltern",
a1.sal "Sal_subaltern",
a2.ename "Nume_sef",
a2.sal "Sal_sef"
from
emp a1
inner join dept d1
on a1.deptno = d1.deptno
inner join emp a2
on a1.mgr = a2.empno and a1.sal >= a2.sal / 2
order by a1.ename;

-- Metoda 2
select
d1.dname "Den_dep_subaltern",
a1.ename "Nume_subaltern",
a1.sal "Sal_subaltern",
a2.ename "Nume_sef",
a2.sal "Sal_sef"
from
emp a1
join dept d1
using (deptno)
inner join emp a2
on a1.mgr = a2.empno
where
a1.sal >= a2.sal / 2
order by a1.ename;

-- Metoda 3
select
d1.dname "Den_dep_subaltern",
a1.ename "Nume_subaltern",
a1.sal "Sal_subaltern",
a2.ename "Nume_sef",
a2.sal "Sal_sef"
from
emp a1, emp a2, dept d1
where
a1.deptno = d1.deptno and a1.mgr = a2.empno and a1.sal >= a2.sal / 2
order by a1.ename;

2. Sa se faca o lista cu toți anagajații pentru care șeful lor nu lucrează în același departament
ca ei. Afișați: numele departamentului în care lucrează angajatul, numele angajatului,
funcția angajatului, numele departamentului în care lucreaza șeful, numele șefului și
funcția șefului. Ordonați după numele angajaților. Se se rezolve folosind doua metode
distincte de join.

REZOLVARI

-- Varianta 1
SELECT
d1.dname "Dep angajat",
e1.ename "Nume angajat",
e1.job "Functie angajat",
d2.dname "Dep sef",
e2.ename "Nume sef",
e2.job "Functie sef"
FROM
emp e1
LEFT JOIN dept d1 ON e1.deptno = d1.deptno
LEFT JOIN emp e2 ON e1.mgr = e2.empno
LEFT JOIN dept d2 ON e2.deptno = d2.deptno
WHERE
e1.deptno != e2.deptno
ORDER BY e1.ename;

-- Varianta 2
SELECT
d1.dname "Dep angajat",
e1.ename "Nume angajat",
e1.job "Functie angajat",
d2.dname "Dep sef",
e2.ename "Nume sef",
e2.job "Functie sef"
FROM
emp e1
INNER JOIN dept d ON e1.deptno = d1.deptno
INNER JOIN emp e2 ON e1.mgr = e2.empno
INNER JOIN dept d2 ON e2.deptno = d2.deptno
WHERE
e1.deptno != e2.deptno
ORDER BY e1.ename;

3. Creati scriptul Oracle SQL pentru rezolvarea urmatoarei cerinte, utilizand metode de 
JOIN: 
Să se selecteze, pentru fiecare angajat ce nu il are ca sef pe KING si care castiga mai mult 
(venitul) decat seful său: numele angajatului, denumirea departamentului din care face 
parte, data angajarii, numele șefului său, denumirea departamentului din care face parte 
șeful său, data angajării șefului. Nu se va afisa angajatul SCOTT. Se se rezolve folosind 
doua metode distincte de join. 
VARIANTA 1
select
e1.ename "Nume angajat",
d1.dname "Dep angajat",
e1.hiredate "Data angajat",
e2.ename "Nume sef",
d2.dname "Dept sef",
e2.hiredate "Data sef"
from emp e1
INNER JOIN dept d1 ON e1.deptno = d1.deptno
INNER JOIN emp e2 ON e1.mgr = e2.empno
INNER JOIN dept d2 ON e2.deptno = d2.deptno
where
e1.mgr != 7839 and (e1.sal+nvl(e1.comm, 0)) > (e2.sal+nvl(e2.comm, 0)) and
e1.ename != 'SCOTT';

VARIANTA 2
select
e1.ename "Nume angajat",
d1.dname "Dep angajat",
e1.hiredate "Data angajat",
e2.ename "Nume sef",
d2.dname "Dept sef",
e2.hiredate "Data sef"
from emp e1
left JOIN dept d1 ON e1.deptno = d1.deptno
left JOIN emp e2 ON e1.mgr = e2.empno
left JOIN dept d2 ON e2.deptno = d2.deptno
where
e1.mgr != 7839 and (e1.sal+nvl(e1.comm, 0)) > (e2.sal+nvl(e2.comm, 0)) and
e1.ename != 'SCOTT';

4. Pentru toate gradele salariale și toate departamentele, să se afișeze gradul salarial, 


numele departamentului, numele angajaților și o primă. Prima este 15% din venitul lunar 
pentru angajații care nu au comision. Gradul pentru un angajat este determinat pe baza 
primei. Ordonați crescător după primă și descrescator după numele departamentului. Se 
se rezolve folosind doua metode distincte de join. 
REZOLVARE: 
METODA 1: 
 
select  
g.grade "Grad salarial",  
d.dname "Nume departament",  
a.ename "Nume salariat",  
(0.15 * (a.sal + nvl(a.comm, 0))) "Prima"  
from emp a 
full outer join  
dept d  
on a.deptno = d.deptno 
full outer join  
salgrade g  
on a.sal between g.losal and g.hisal 
where (a.comm = 0 or a.comm is null)  
order by "Prima" asc, d.dname desc; 
 
METODA 2: 
 
SELECT  
g.grade "Grad salarial", 
d.dname "Nume departament", 
a.ename "Nume salariat", 
(0.15 * (a.sal + nvl(a.comm, 0))) "Prima"  
FROM emp a 
LEFT OUTER JOIN  
dept d  
ON a.deptno = d.deptno 
FULL OUTER JOIN  
salgrade g 
ON a.sal BETWEEN g.losal AND g.hisal 
WHERE (a.comm = 0 or a.comm IS NULL) ORDER BY "Prima" ASC, d.dname DESC; 

5.​Sa se faca o lista cu angajatii al caror sef are venitul lunar mai mare de 3000. Lista se 
va ordona dupa numele subalternilor. Antetul listei este: 
Nume_subaltern Venit_subaltern Grad_sal_subaltern Nume_sef Venit_sef Grad_sal_sef 

Se se rezolve folosind doua metode distincte de join. 

--metoda 1

SELECT a1.nume, a1.salariu, a2.nume, a2.salariu


FROM angajati a1
INNER JOIN angajati a2
ON a1.id_sef = a2.id_ang
WHERE
a2.salariu > 3000
ORDER BY a1.nume;

--metoda 2
SELECT a1.nume, a1.salariu, a2.nume, a2.salariu
FROM angajati a1
LEFT OUTER JOIN angajati a2
ON a1.id_sef = a2.id_ang
WHERE
a2.salariu > 3000
ORDER BY a1.nume;

Nu pare ok aici. Arata incomplet. Cred ca e mai ok asa


select
e1.ename "Nume_subaltern",
e1.sal "Venit_subaltern",
g1.grade "Grad_sal_subaltern",
e2.ename "Nume_sef",
e2.sal "Venit_sef",
g2.grade "Grad_sal_sef"
from emp e1
join emp e2
on e1.mgr=e2.empno
join salgrade g1
on e1.sal between g1.losal and g1.hisal
join salgrade g2
on e2.sal between g2.losal and g2.hisal
where e2.sal > 3000
order by e1.ename;

TEST LAB 6

1.​Sa se scrie o cerere SQL care face o lista cu numarul de aparitii ale ultimelor 2 litere
din numele angajatului(exact in ordinea literelor) care se regasesc in jobul angajatului(exact in
acea ordine si succesive). Antetul listei este urmatorul:
Nume_angajat, Job, Nr_aparitii
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL.
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE.

REZOLVARE
select ename "Nume_angajat", job "Job",
(LENGTH(job) - LENGTH(REPLACE(job,
SUBSTR(ename, LENGTH(ename)-1), '')))/2 "Nr_aparitii" from emp;

select ename "Nume_angajat", job "Job",


(LENGTH(RTRIM(job)) - LENGTH(replace(RTRIM(job),
SUBSTR(ename, LENGTH(ename)-1), '')))/2 "Nr_aparitii" from emp;

2. ​Sa se faca o lista cu toți anagajații pentru care șeful lor nu lucrează în același
departament ca ei. Afișați: numele departamentului în care lucrează angajatul, numele
angajatului, funcția angajatului, numele departamentului în care lucreaza șeful, numele șefului și
funcția șefului. Ordonați după numele angajaților. Se se rezolve folosind doua metode distincte
de join.

REZOLVARE

-- Varianta 1
SELECT
d1.dname "Dep angajat",
e1.ename "Nume angajat",
e1.job "Functie angajat",
d2.dname "Dep sef",
e2.ename "Nume sef",
e2.job "Functie sef"
FROM
emp e1
LEFT JOIN dept d1 ON e1.deptno = d1.deptno
LEFT JOIN emp e2 ON e1.mgr = e2.empno
LEFT JOIN dept d2 ON e2.deptno = d2.deptno
WHERE
e1.deptno != e2.deptno
ORDER BY e1.ename;

-- Varianta 2
SELECT
d1.dname "Dep angajat",
e1.ename "Nume angajat",
e1.job "Functie angajat",
d2.dname "Dep sef",
e2.ename "Nume sef",
e2.job "Functie sef"
FROM
emp e1
INNER JOIN dept d ON e1.deptno = d.deptno
INNER JOIN emp e2 ON e1.mgr = e2.empno
INNER JOIN dept d2 ON e2.deptno = d2.deptno
WHERE
e1.deptno != e2.deptno
ORDER BY e1.ename;
3. Sa se afiseze pentru toti angajatii care s-au angajat inaintea sefului lor si au gradul de 
salarizare mai mare sau egal cu 3, numarul intreg de zile de concediu la care au dreptul, 
calculat dupa formula   
  zile=abs(sin(sqrt(vec*grad))*150)   
unde 
  vec=vechime in ani nerotunjita 
  grad=gradul din grila de salarizare 
Lista are antetul nume, grad, concediu si se ordoneaza alfabetic. 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 

VARIANTA 1
select
e1.ename "Nume",
g.grade "Grad",
ROUND(abs(sin(sqrt((months_between(sysdate, e1.hiredate) / 12) * g.grade)) *150))
"Concediu"
from
emp e1
INNER JOIN salgrade g ON e1.sal between g.losal and g.hisal
INNER JOIN emp e2 ON e1.mgr = e2.empno
where
e1.hiredate < e2.hiredate and
g.grade >= 3
order by e1.ename;

VARIANTA 2
select
INITCAP(e1.ename) "Nume",
g.grade "Grad",
ROUND(abs(sin(sqrt((months_between(sysdate, e1.hiredate) / 12) * g.grade)) *150))
"Concediu"
from
emp e1
INNER JOIN salgrade g ON e1.sal between g.losal and g.hisal
INNER JOIN emp e2 ON e1.mgr = e2.empno
where
sign(e2.hiredate - e1.hiredate) > 0 and
sign(g.grade - 3) >= 0
order by e1.ename;

4. Sa se scrie o cerere SQL care face o lista cu angajatii care primesc o prima de 10% din 
salariu. 
Prima se acorda in luna in care s-au angajat. Conditiile pentru acordarea primei sunt: 
- Vechime de peste 25 ani in companie; 
- Angajatii nu au primit commision. 
Antetul listei este urmatorul: 
Den_dep, Nume, Data_ang, Den_luna_prima, Salariu, Comision, Prima 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 

METODA 1:
select
d.dname DEN_DEP,
a.ename NUME,
a.hiredate DATA_ANG,
substr('JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC ',
(extract(MONTH from a.hiredate) * 4) - 3, 3) DEN_LUNA_PRIMA,
a.sal SALARIU,
a.comm COMISION,
(0.1 * a.sal) PRIMA
from
emp a
dept d
where
a.deptno = d.deptno
and
(a.comm = 0 or a.comm is null)
and
months_between(sysdate, a.hiredate) > 25 * 12;
METODA 2:
select
d.dname DEN_DEP,
a.ename NUME,
a.hiredate DATA_ANG,
to_char(a.hiredate, 'MONTH') DEN_LUNA_PRIMA,
a.sal SALARIU,
a.comm COMISION,
(0.1 * a.sal) PRIMA
from
emp a
join
dept d
on
a.deptno = d.deptno
where
(a.comm = 0 or a.comm is null)
and
months_between(sysdate, a.hiredate) > 25 * 12;

5.Pentru angajatii ce au aceeai paritate a lungimii numelui ca cea a sefului lor (daca nu au 
sef se considera ca indeplinesc aceasta conditie), faceti o lista cu: 
- numele departamentului lor si al celui in care este seful, scris cu litere mari si separate 
prin virgula (NUME_DEPT) 
- cate luni complete au lucrat in firma in care(LUNI_LUCRATE_ANG) 
- initiala numelui lor, ca litera mica (INITIALA_ANG) 
- ultima cifra a venitului lor (ULTIMA_CIFRA_SALARIU) 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 
--metoda 1 (concatenare cu ajutorul concat)
select concat(concat(d1.dname,','), d2.dname) "NUME_DEPT",
floor(MONTHS_BETWEEN(sysdate, e1.hiredate)) "LUNI_LUCRATE_ANG",
LOWER(SUBSTR(e1.ename,1,1)) "INITIALA_ANG",
MOD(e1.sal , 10) "ULTIMA_CIFRA_SALARIU"
from emp e1, emp e2, dept d1, dept d2
where e1.mgr=e2.empno and e1.deptno=d1.deptno and
e2.deptno=d2.deptno and
(mod(LENGTH(e1.ename),2)=mod(LENGTH(e2.ename),2) or
e1.mgr is null);

--metoda 2 (concatenare cu ajutorul operatorului || )


select d1.dname||','||d2.dname "NUME_DEPT",
floor(MONTHS_BETWEEN(sysdate, e1.hiredate)) "LUNI_LUCRATE_ANG",
LOWER(SUBSTR(e1.ename,1,1)) "INITIALA_ANG",
MOD((e1.sal) , 10) "ULTIMA_CIFRA_SALARIU"
from emp e1, emp e2, dept d1, dept d2
where e1.mgr=e2.empno and e1.deptno=d1.deptno and
e2.deptno=d2.deptno and
(mod(LENGTH(e1.ename),2)=mod(LENGTH(e2.ename),2) or
e1.mgr is null);

TEST LAB 7
1.​Sa se scrie o cerere SQL care face o lista de premiere a angajatilor aplicand urmatoarele
criterii:
a) Angajatii care au primit comision primesc o prima egala cu salariul mediu pe companie;
b) Angajatii care nu au primit comision primesc o prima egala cu salariul minim pe companie;
c) Presedintele si directorii nu primesc prima.
Antetul listei este urmatorul:
Den_part, Nume_ang, Job, Comision, Salariu_min_com, Sal_mediu_com, Prima
Obs. Salariile si prima se afiseaza fara zecimale.
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

REZOLVARE

column "Prima" format 99999999


column "Sal_mediu_com" format 99999999
select
d.dname "Den_part",
e.ename "Nume_ang",
e.job "Job",
nvl(e.comm, 0) "Comision",
(select min(sal) from emp) "Salariu_min_com",
(select avg(sal) from emp) "Sal_mediu_com",
case when e.job in ('PRESIDENT', 'MANAGER') then 0
when nvl(e.comm, 0) > 0 then (select avg(sal) from emp)
else (select min(sal) from emp)
end "Prima"
from emp e
join dept d
on d.deptno = e.deptno
group by
d.dname, e.ename, e.job, e.comm;

2. Sa se faca o lista cu numarul de subalterni care nu au functia 'MANAGER' si media 


veniturilor acestora (al subalternitor) grupate dupa numele functiei si numele sefului lor. 
Sa se afiseze doar liniile unde numarul de sublaterni este mai mare sau egala cu 2. 
Lista are urmatorul antet 
- Nume sef, 
- Numele functiei subalternilor 
- Numar subalterni care nu au functia 'MANAGER' 
- Media veniturilot sublaternilor care nu au functia 'MANAGER' 
Ordonati descrescator dupa numele sefului. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
select
b.ename "Nume_sef",
e.job "Functie_subalterni",
count(e.empno) "Nr_subalt_not_MANAGER",
avg(e.sal) "Avg_venit_subalterni_not_MANAGER"
from
emp b
join emp e on b.empno = e.mgr and e.job not like 'MANAGER'
having
count(e.empno) >= 2
group by
b.ename, e.job
order by
b.ename desc;

3. Pentru angajatii din departamentul 'RESEARCH' afisati: 


- primele 3 caractere din functie, daca s-au angajat in anul 1981, 
- ultimele 3 caractere din functie, daca s-au angajat in anul 1982, respectiv 
- numele intreg al functiei, in celelalte cazuri. 
Ordonati dupa coloana care afisaza functia astfel calculata. 
Antetul listei va fi urmatorul: 
Nume_ang, Nume_dept, Sir_functie_ang. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
REZOLVARE
select a.ename "Nume_ang",
d.dname "Nume_dept",
case (to_char(a.hiredate, 'YYYY'))
when '1981' then substr(a.job, 1, 3)
when '1982' then substr(a.job, length(a.job) - 2, 3)
else a.job
end "Sir_functie_ang"
from emp a
join dept d
on a.deptno = d.deptno and d.dname like 'RESEARCH'
order by 3;

4. ​Sa se afiseze, pentru toti angajatii departamentului SALES, o lista care sa contina o 
apreciere a venitului anual al angajatului precum si numarul de subordonati direct ai 
angajatului respectiv. 
Aprecierea venitului anual se va face astfel : 
- Daca venitul anual este <= 12000, atunci venitul anual este SCAZUT 
- Daca venitul anual este intre 12001 si 22000, atunci venitul anual este MEDIU 
- Daca venitul anual este peste 22000, atunci venitul anual este RIDICAT 
Lista va afisa si angajatii care nu au subordonati. 
Antetul listei este urmatorul: 
Nume_angajat, Venit_anual, Apreciere_venit, Nr_subordonati. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

REZOLVARE:

define venit='12*e.sal+nvl(e.comm,0)'
select e.ename "Nume_angajat",
&venit "Venit_anual",
case when &venit <= 12000 then 'SCAZUT'
when &venit > 22000 then 'RIDICAT'
else 'MEDIU'
end "Apreciere_venit",
count(e1.empno) "Nr_subordonati"
from emp e
left outer join emp e1
on e.empno = e1.mgr
join dept d
on e.deptno = d.deptno and d.dname like 'SALES'
group by
e.ename, e.sal, e.comm;
undefine venit

5.​Sa se scrie o cerere SQL care face o lista de premiere a angajatilor aplicand urmatoarele 
criterii: 
a) Angajatii care au primit comision primesc o prima egala cu jumatate din salariul 
maxim pe companie; 

b) Angajatii care nu au primit comision primesc o prima egala cu salariul minim pe 
companie; 

c) Presedintele si directorii nu primesc prima. 

Antetul listei este urmatorul: 

Den_part, Nume_ang, Comision, Salariu_min_com, Sal_max_com, Prima 


Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

 
SELECT 
d.dname Den_part, 
e.ename Nume_ang, 
e.comm Comision, 
min (e.sal) Salariu_min_com, 
max (e.sal) Salariu_max_com, 
case 
when ((e.job LIKE 'MANAGER') or (e.job LIKE 'PRESIDENT')) then 0 
when e.comm IS NULL THEN min (e.sal) 
when e.comm IS NOT NULL THEN max(e.sal) / 2 
end Prima 
FROM emp e JOIN dept d 
ON e.deptno = d.deptno 
GROUP BY d.dname, e.ename, e.job, e.comm; 
 
 

TEST LAB 8
1.​Sa se calculeze, pentru fiecare angajat ce are, in departamentul sau, cel putin doi angajati cu un
salariu mai mic decat el si care a venit in firma dupa seful sau direct: vechimea in ani (valoare
intreaga), gradul salarial si diferenta dintre salariul sefului sau si salariul sau.
Antetul listei de afisat trebuie sa fie :
Nume angajat, Denumire departament, Ani vechime, Grad, Diferenta salariu sef
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

REZOLVARE
select
e.ename "Nume angajat",
d.dname "Denumire departament",
CEIL(MONTHS_BETWEEN(sysdate, e.hiredate) / 12) "Ani vechime",
g.grade "Grad",
b.sal - e.sal "Diferenta salariu sef"
from
emp e
join dept d
on d.deptno = e.deptno
join emp b
on b.empno = e.mgr
join salgrade g
on e.sal between g.losal and g.hisal
where
(select
count(*)
from
emp e1
where
e1.deptno = e.deptno and e.sal > e1.sal) >= 2
and
e.hiredate > b.hiredate;

2. ​Sa se scrie o cerere SQL care face o lista cu sefii de departament care primesc un
bonus la salariu aplicand urmatoarele criterii:
- sefii care au primit comision, primesc ca prima salariul mediu pe departamentul din care fac
parte;
- sefii care nu au primit comision primesc ca prima salariul minim pe departamentul din care fac
parte.
Antetul listei este urmatorul:
Den_depart, Nume_ang, Comision, Sal_min_dep, Sal_mediu_dep, Prima
Salariul mediu pe departament se afiseaza fara zecimale.
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

REZOLVARE

column "Sal_mediu_dep" format 9999999


select
d.dname "Den_depart",
e.ename "Nume_ang",
e.comm "Comision",
(select min(e2.sal) from emp e2 where e.deptno = e2.deptno) "Sal_min_dep",
(select avg(e3.sal) from emp e3 where e.deptno = e3.deptno) "Sal_mediu_dep",
case when nvl(e.comm,0) > 0 then (select avg(e3.sal) from emp e3 where e.deptno
= e3.deptno)
else (select min(e2.sal) from emp e2 where e.deptno = e2.deptno)
end "Prima"
from emp e
inner join dept d
on e.deptno = d.deptno
where
job in ('MANAGER', 'PRESIDENT');
3. Sa se acorde o bonificatie tuturor angajatilor care au salariul mai mare decit salariul 
mediu in departamentul in care lucreaza presedintele. Bonificatia reprezinta 25% din 
diferenta intre salariul angajatului si salariul mediu pe companie, rotunjita la doua 
zecimale. 
Lista are antetul nume, functie, salariu, bonificatie si va fi ordonata crescator dupa salariu 
si nume. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

REZOLVARE
select
ename "nume",
job "functie",
sal "salariu",
round((sal - (select avg(sal) from emp)) * 0.25, 2) "bonificatie"
from emp
where sal >
(
select
avg(sal)
from emp
where deptno =
(
select
deptno
from emp
where job like 'PRESIDENT'
)
)
order by 3,1;
4.​a se afiseze angajatii care nu lucreaza in orasele DALLAS si CHICAGO si s-au angajat 
inaintea sefului lor direct cu cel putin 4 luni. Se va afisa numele angajatilor, salariul 
acestora, orasul unde lucreaza, numele sefului direct si salariul sefului direct. 
Lista are antetul nume, salariu, locatie, sef, salariu_sef. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

SELECT
e1.ename Nume,
e1.sal Salariu,
d1.loc Locatie,
e2.ename Sef,
e2.sal Salariu_sef
FROM
emp e1 NATURAL JOIN dept d1
INNER JOIN emp e2
ON e1.mgr = e2.empno
WHERE
months_between(e2.hiredate, e1.hiredate) >= 4 AND
d1.loc NOT IN (SELECT loc FROM dept WHERE loc = 'DALLAS' OR loc =
'CHICAGO');

TEST LAB 9-10

1. Să se creeze tabela Statistica_Sefi, cu următoarele coloane: 

- Nume_Sef 

- Venit_Sef 

- Grila_Salariala_Subalterni (grila salarială a subalternilor pentru care el este șef) 

- Numar_Subalterni (numărul subalternilor pentru acest șef cu această grilă) 

- Medie_Venit_Subalterni (media veniturilor subalternilor cu acea grila salarială) 


Să se populeze tabela în conformitate cu aceste cerințe pentru fiecare șef din 
companie, persoană din tabela EMP care are minim un subaltern, care este din același 
departament cu minim un subaltern. 

Pentru testare, se va utiliza baza de date formata din tabelele EMP, DEPT si 
SALGRADE. 

create table Statistica_Sefi 


as 
select e.ename "Nume_Sef", 
e.sal + nvl(e.comm, 0) "Venit_sef", 
(select count(empno)  
from emp  
where  
mgr = e.empno and deptno = e.deptno 
) "Numar_subalterni", 
(select avg(sal + nvl(comm, 0))  
from emp  
where mgr = e.empno and deptno = e.deptno 
)"Medie_Venit_Subalterni" 
from emp e join dept d 
on e.deptno = d.deptno 
where (select count(empno)  
from emp  
where  
mgr = e.empno and deptno = e.deptno 
) >= 1; 
 

Test LAB 5
1. Sa se faca o lista cu angajatii al caror sef are venitul lunar mai mare de 3000. Lista se va
ordona dupa numele subalternilor. Antetul listei este:

Nume_subaltern Venit_subaltern Grad_sal_subaltern Nume_sef Venit_sef Grad_sal_sef

Se se rezolve folosind doua metode distincte de join​.

Solutie:
-- Metoda 1 Join
select
a1.ename "Nume_subaltern",
a1.sal+nvl(a1.comm,0) "Venit_subaltern",
g1.grade "Grad_sal_subaltern",
a2.ename "Nume_sef",
a2.sal+nvl(a2.comm,0) "Venit_sef",
g2.grade "Grad_sal_sef"
from
emp a1
inner join emp a2
on a1.mgr = a2.empno
inner join salgrade g2
on (a2.sal+nvl(a2.comm,0) between g2.losal and g2.hisal) and a2.sal+nvl(a2.comm,0) > 3000
inner join salgrade g1
on a1.sal+nvl(a1.comm,0) between g1.losal and g1.hisal
order by
a1.ename;

-- Metoda 2
select
a1.ename "Nume_subaltern",
a1.sal+nvl(a1.comm,0) "Venit_subaltern",
g1.grade "Grad_sal_subaltern",
a2.ename "Nume_sef",
a2.sal+nvl(a2.comm,0) "Venit_sef",
g2.grade "Grad_sal_sef"
from
salgrade g1, salgrade g2, emp a2, emp a1
where
a1.mgr = a2.empno and
(a1.sal+nvl(a1.comm,0) between g1.losal and g1.hisal) and
(a2.sal+nvl(a2.comm,0) between g2.losal and g2.hisal) and
a2.sal+nvl(a2.comm,0) > 3000
order by
a1.ename;

-- Metoda 3
select
a1.ename "Nume_subaltern",
a1.sal+nvl(a1.comm,0) "Venit_subaltern",
g1.grade "Grad_sal_subaltern",
a2.ename "Nume_sef",
a2.sal+nvl(a2.comm,0) "Venit_sef",
g2.grade "Grad_sal_sef"
from
salgrade g1, salgrade g2, emp a1
join emp a2
on a1.mgr = a2.empno
where
(a1.sal+nvl(a1.comm,0) between g1.losal and g1.hisal) and
(a2.sal+nvl(a2.comm,0) between g2.losal and g2.hisal) and
a2.sal+nvl(a2.comm,0) > 3000
order by
a1.ename;

2. Sa se scrie o cerere SQL care face o lista cu toti angajatii care au acelasi departament cu
cel al sefului direct si au venit in companie in anul 1981. Lista se ordoneaza dupa numele
subalternilor si are urmatorul antet:

Den_dep Nume_subaltern Data_ang_subaltern Nume_sef Data_ang_sef

Se se rezolve folosind doua metode distincte de join.


Solutie:
-- METODA 1 --

SELECT
D.DNAME Den_dep,
E1.ENAME Nume_subaltern,
E1.HIREDATE Data_ang_subaltern,
E2.ENAME Nume_sef,
E2.HIREDATE Data_ang_sef
FROM dept D, emp E1, emp E2
WHERE
E1.DEPTNO = E.DEPTNO and
E1.DEPTNO = E2.DEPTNO and
E1.MGR = E2.EMPNO and
E1.HIREDATE like “%81”
ORDER BY E1.ENAME;

-- METODA 2 --

SELECT
D.DNAME Den_dep,
E1.ENAME Nume_subaltern,
E1.HIREDATE Data_ang_subaltern,
E2.ENAME Nume_sef,
E2.HIREDATE Data_ang_sef
FROM dept D, emp E1
INNER JOIN emp E2 ON
E1.DEPTNO = E2.DEPTNO and
E1.MGR = E2.EMPNO
WHERE
E1.DEPTNO = E.DEPTNO and
E1.HIREDATE like “%81”
ORDER BY E1.ENAME;

EDIT: metodele de mai sus dau eroare, am facut alta, sper ca returneaza ce trebuie:

select
d.dname "Den_dep",
e1.ename "Nume_subaltern",
e1.hiredate "Data_ang_subaltern",
e2.ename "Nume_sef",
e2.hiredate "Data_ang_sef"
from emp e1
inner join emp e2 on e1.mgr = e2.empno and extract(year from e2.hiredate) = 1981 and e1.deptno =
e2.deptno
inner join dept d on e1.deptno = d.deptno
order by e1.ename;

3.​Sa se faca o lista cu toți anagajații pentru care șeful lor nu lucrează în același 
departament ca ei. Afișați: numele departamentului în care lucrează angajatul, numele 
angajatului, funcția angajatului, numele departamentului în care lucreaza șeful, numele 
șefului și funcția șefului. Ordonați după numele angajaților. Se se rezolve folosind doua 
metode distincte de join. 
Solutie: 
-- varianta 1: inner join 
SELECT 
d1.dname "Departament Angajat", 
e1.ename "Nume Angajat", 
e1.job "Functie Angajat", 
d2.dname "Departament Sef", 
e2.ename "Nume Sef", 
e2.job "Functie Sef" 
FROM 
emp e1 
inner join emp e2 
on e1.mgr = e2.empno and e1.deptno != e2.deptno 
inner join dept d1 
on e1.deptno = d1.deptno 
inner join dept d2 
on e2.deptno = d2.deptno 
ORDER BY e1.ename; 
 
-- varianta 2: inner + outer join 
SELECT 
d1.dname "Departament Angajat", 
e1.ename "Nume Angajat", 
e1.job "Functie Angajat", 
d2.dname "Departament Sef", 
e2.ename "Nume Sef", 
e2.job "Functie Sef" 
FROM 
emp e1 
inner join emp e2 
on e1.mgr = e2.empno 
left outer join dept d2 
on e2.deptno = d2.deptno 
left outer join dept d1 
on e1.deptno = d1.deptno 
WHERE 
e1.deptno != e2.deptno 
ORDER BY e1.ename; 
 
-- varianta 3: where clause (inner join) 
 
select 
d1.dname "Departament Angajat", 
e1.ename "Nume Angajat", 
e1.job "Functie Angajat", 
d2.dname "Departament Sef", 
e2.ename "Nume Sef", 
e2.job "Functie Sef" 
FROM 
emp e1, dept d1, emp e2, dept d2 
WHERE e1.mgr = e2.empno and e1.deptno != e2.deptno and e1.deptno = d1.deptno and 
e2.deptno = d2.deptno 
ORDER BY e1.ename; 
 
virful cistigului mai mare decit 1 (EEA remember??????) pls ​answer 
 
4. ​Sa se faca o lista cu toti angajatii care au salariul mai mare ​decit​ sefii lor. Afisati numele 
angajatului, functia angajatului, numele managerului, departamentul angajatului, locatia 
angajatului precum si gradatia salariala a angajatului (grad). Antetul listei va fi ang, 
func_ang, sef, depart, locatie, gradatie. Se va ordona alfabetic dupa numele angajatilor. Se 
se rezolve folosind doua metode distincte de join. 
 
select a1.ename "Nume angajat", a1.job "Functie angajat", a2.ename "Nume manager", 
d.dname "Departament angajat", d.loc "Locatie angajat", g.grade "Grad angajat" 
from emp a1 
join dept d 
on a1.deptno = d.deptno 
join emp a2 
on a1.mgr = a2.empno 
join salgrade g 
on a1.sal between g.losal and g.hisal 
where a1.sal > a2.sal 
order by a1.ename; 
 
 
 
select a1.ename "Nume angajat", a1.job "Functie angajat", a2.ename "Nume manager", 
d.dname "Departament angajat", d.loc "Locatie angajat", g.grade "Grad angajat" 
from emp a1 
left join dept d 
on a1.deptno = d.deptno 
left outer join emp a2 
on a1.mgr = a2.empno 
left join salgrade g 
on a1.sal between g.losal and g.hisal 
where a1.sal > a2.sal 
order by a1.ename; 
 
 

5. Să se facă o lista cu numele angajatului, numele departamentului în care


lucrează angajatul, data angajării, funcția anajatului, numele șefului, numele
departamentului in care lucreaza șeful, data angajării șefului și funcția șefului
pentru toți angajații care au funcția diferită de ‘MANAGER’, nu au comision și au
venit în firmă în același an ca șeful lor. Ordonați după salariul șefului descrescăror
și funcția angajatului crescător. Se se rezolve folosind doua metode distincte de
join.

--Metoda 1:
SELECT
a1.ename "Nume angajat",
d1.dname "Nume departament",
a1.hiredate "Data angajare",
a1.job "Functie angajat",
a2.ename "Nume sef",
d2.dname "Nume departament sef",
a2.hiredate "Data angajare sef",
a2.job "Functie sef"
FROM
emp a1
INNER JOIN emp a2
INNER JOIN dept d2
ON a2.deptno = d2.deptno
ON a1.mgr = a2.empno AND
extract(YEAR FROM a1.hiredate) = extract(YEAR FROM a2.hiredate)
INNER JOIN dept d1
ON a1.deptno = d1.deptno
WHERE
(a1.comm = 0 OR a1.comm IS NULL) AND a1.job != 'MANAGER'
ORDER BY
a1.job, a2.sal DESC;

--Metoda 2:
SELECT
a1.ename "Nume angajat",
d1.dname "Nume departament",
a1.hiredate "Data angajare",
a1.job "Functie angajat",
a2.ename "Nume sef",
d2.dname "Nume departament sef",
a2.hiredate "Data angajare sef",
a2.job "Functie sef"
FROM
emp a1
INNER JOIN emp a2
ON a1.mgr = a2.empno AND
extract(YEAR FROM a1.hiredate) = extract(YEAR FROM
a2.hiredate)
LEFT OUTER JOIN dept d2
ON a2.deptno = d2.deptno
LEFT OUTER JOIN dept d1
ON a1.deptno = d1.deptno
WHERE
(a1.comm = 0 OR a1.comm IS NULL) AND LOWER(a1.job) NOT LIKE 'manager'
ORDER BY
a1.job, a2.sal DESC;

6. ​Sa se scrie o cerere SQL care face o lista cu toti angajatii care au salariul mai mare 
decat jumatate din salariul sefului direct. Lista se ordoneaza dupa numele subalternilor si 
are urmatorul antet:  
Den_dep_subaltern Nume_subaltern Sal_subaltern Nume_sef Sal_sef 
Se se rezolve folosind doua metode distincte de join. 

-- metoda 1 (left outer join + join)


select d.dname "Den_dep_subaltern", a1.ename "Nume_subaltern", a1.sal "Sal subaltern",
a2.ename "Nume sef", a2.sal "Sal sef"
from emp a1
left outer join emp a2
on a1.mgr = a2.empno
join dept d
on a1.deptno = d.deptno
where a1.sal > a2.sal / 2
order by a1.ename;

-- metoda 2 (inner join + join)


select d.dname "Den_dep_subaltern", a1.ename "Nume_subaltern", a1.sal "Sal subaltern",
a2.ename "Nume sef", a2.sal "Sal sef"
from emp a1
join dept d
on a1.deptno = d.deptno
inner join emp a2
on a1.mgr = a2.empno
where a1.sal > a2.sal / 2
order by a1.ename;

7. ​Sa se faca o lista cu angajatii care au salariul mai mare decat salariul sefului direct si 
apartin unui departament cu un nume format din minim 5 caractere. Ordonați lista după 
departamente si numele subalternilor. Antetul listei este: 
Den_dep_subaltern Nume_subaltern Job_subaltern Nume_sef Job_sef 
Se se rezolve folosind doua metode distincte de join. 

--Metoda 1
select
d1.dname "Den_dep_subaltern",
a1.ename "Nume_subaltern",
a1.job "Job_subaltern",
a2.ename "Nume_sef",
a2.job "Job_sef"
from
emp a1
inner join dept d1
on a1.deptno = d1.deptno and d1.dname like '_____%'
inner join emp a2
on a1.mgr = a2.empno and a1.sal > a2.sal
order by d1.dname, a1.ename;

--Metoda2
select
d1.dname "Den_dep_subaltern",
a1.ename "Nume_subaltern",
a1.job "Job_subaltern",
a2.ename "Nume_sef",
a2.job "Job_sef"
from
emp a1
left outer join dept d1
on a1.deptno = d1.deptno
inner join emp a2
on a1.mgr = a2.empno and a1.sal > a2.sal
where
d1.dname like '_____%'
order by d1.dname, a1.ename;

8.​ ​Să se selecteze, pentru fiecare angajat din departamentul lui JONES, ce a venit in firma
dupa JONES : numele angajatului, data angajarii, denumirea departamentului , venitul
său precum si diferenta între venitul său si venitul lui JONES. Se se rezolve folosind
doua metode distincte de join.
-- Prima metoda -> Inner Join:
SELECT
a1.ename "Nume Angajat",
a1.hiredate "Data Angajarii",
d.dname "Departament",
a1.sal * 12 + nvl(a1.comm, 0) "Venit",
a2.sal * 12 + nvl(a1.comm, 0) - a1.sal * 12 + nvl(a2.comm, 0) "Diferenta"
FROM
emp a1,
emp a2,
dept d
WHERE
a1.deptno = d.deptno(+) AND
a2.ename = 'JONES' AND
a1.hiredate > a2.hiredate;

-- A doua metoda:

SELECT
a1.ename "Nume Angajat",
a1.hiredate "Data Angajarii",
d.dname "Departament",
a1.sal * 12 + nvl(a1.comm, 0) "Venit",
a2.sal * 12 + nvl(a1.comm, 0) - a1.sal * 12 + nvl(a2.comm, 0) "Diferenta"
FROM
emp a1
left outer join dept d
on a1.deptno = d.deptno(+)
inner join emp a2
on a2.ename = 'JONES' and (a1.hiredate > a2.hiredate);

Test LAB 6
1. Sa se calculeze o prima pentru angajatii care

● - au lungimea numelui mai mare sau egal cu 5


● - au venit in firma cu cel putin 6 luni in urma seful lor.
Prima se calculeaza dupa urmatoarea formula: salariu * c * |ln(n)/((n^3-2)*cos(n^3-2))| unde

● - n este vechimea in firma calculata in ani cu virgula


● - c este o constanta data de la tastatura (100)

Sa se afiseze:

● - numele angajatului
● - numele departamentul in care lucreaza angajatul
● - data angajarii pentru angajat - afisati doar luna si anul
● - prima
● - numele sefului
● - numele departamentul sefului
● - data angajarii pentru sef - afisati doar luna si anul

Rotunjiti prima la 2 zecimale.

Formatati numelui angajatilor si denumirea departamentele astfel incat sa apara prima litera mare
si restul literelor mici.

Ordonati crescator dupa nume.

Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE.

Solutie:

-- Metoda 1
select
initcap(e.ename) "Nume_ang",
initcap(de.dname) "Den_dept_ang",
to_char(e.hiredate, 'MM-YYYY') "Data_angajare_ang",
round(e.sal * &c * abs(ln(months_between(sysdate, e.hiredate) / 12)
/ (power(months_between(sysdate, e.hiredate) / 12, 3) - 2)
* cos(power(months_between(sysdate, e.hiredate) / 12, 3) - 2)),
2) "Prima",
initcap(m.ename) "Nume_sef",
initcap(dm.dname) "Den_dept_sef",
to_char(m.hiredate, 'MM-YYYY') "Data_angajare_sef"
from
emp e
join dept de on e.deptno = de.deptno
inner join emp m on e.mgr = m.empno
inner join dept dm on m.deptno = dm.deptno
where length(e.ename) >= 5 and months_between(e.hiredate, m.hiredate) >= 6 order by e.ename;

-- Metoda 2
select
initcap(e.ename) "Nume_ang",
initcap(de.dname) "Den_dept_ang",
to_char(e.hiredate, 'MM-YYYY') "Data_angajare_ang",
round(e.sal * &c * abs(ln(months_between(sysdate, e.hiredate) / 12)
/ (power(months_between(sysdate, e.hiredate) / 12, 3) - 2)
* cos(power(months_between(sysdate, e.hiredate) / 12, 3) - 2)),
2) "Prima",
initcap(m.ename) "Nume_sef",
initcap(dm.dname) "Den_dept_sef",
to_char(m.hiredate, 'MM-YYYY') "Data_angajare_sef"
from
emp e, dept de, emp m, dept dm
where
length(e.ename) >= 5 and
months_between(e.hiredate, m.hiredate) >= 6 and e.deptno = de.deptno and e.mgr = m.empno
and m.deptno = dm.deptno
order by
e.ename;

2. Pentru angajatii ce au numele de lungime mai mare ca a sefului lor (daca nu au sef se
considera ca indeplinesc aceasta conditie), faceti o lista cu:

● - numele departamentului in care este seful, scris cu litere mari (NUME_DEPT_SEF)


● - cate luni complete au lucrat in firma (LUNI_LUCRATE_ANG)
● - initiala numelui lor, ca litera mica (INITIALA_ANG)
● - ultima cifra a venitului lor (ULTIMA_CIFRA_SALARIU)

Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL.

Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE


Solutie:
--Metoda 1

SELECT
UPPER(D.DNAME) NUME_DEPT_SEF,
TRUNC(MONTHS_BETWEEN(sysdate, E1.HIREDATE)) LUNI_LUCRATE_ANG,
LOWER(SUBSTR(E1.ENAME, 0, 1)) INITIALA_ANG,
MOD(E1.SAL,10) ULTIMA_CIFRA_SALARIU
FROM dept D, emp E1, emp E2
WHERE
E2.DEPTNO = D.DEPTNO and
E1.MGR = E2.EMPNO and
LENGTH(E1.ENAME) > LENGTH(E2.ENAME);

--Metoda 2

SELECT
UPPER(D.DNAME) NUME_DEPT_SEF,
TRUNC(MONTHS_BETWEEN(sysdate, E1.HIREDATE)) LUNI_LUCRATE_ANG,
LOWER(SUBSTR(E1.ENAME, 0, 1)) INITIALA_ANG,
SUBSTR(E1.SAL,LENGTH(E1.SAL), 1) ULTIMA_CIFRA_SALARIU
FROM dept D, emp E1
LEFT OUTER JOIN emp E2 ON
E1.MGR = E2.EMPNO
WHERE
LENGTH(E1.ENAME) > LENGTH(E2.ENAME) and
E2.DEPTNO = D.DEPTNO;

3. Sa se scrie o cerere SQL care face o lista cu angajatii care au o vechime in firma 
mai mare de un an. Pentru fiecare angajat se vor afisa: Numele angajatului, ultima 
litera din numele lui, ziua in care s-a angajat acesta, vechimea lui in luni si numele 
departamenului urmat de 3 *. Ordonati lista dupa vechime. 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 
Solutie:
-- varianta 1
SELECT e1.ename Nume,
SUBSTR(e1.ename, LENGTH(e1.ename)) Ultima_litera,
EXTRACT(DAY FROM e1.hiredate) Ziua,
MONTHS_BETWEEN(sysdate, e1.hiredate) Vechime,
CONCAT(d1.dname, '***') Dept_nume
FROM emp e1 inner join dept d1 on e1.deptno = d1.deptno
WHERE MONTHS_BETWEEN(sysdate, e1.hiredate) > 12
ORDER BY Vechime;

-- varianta 2
SELECT e1.ename Nume,
SUBSTR(e1.ename, LENGTH(e1.ename)) Ultima_litera,
EXTRACT(DAY FROM e1.hiredate) Ziua,
MONTHS_BETWEEN(sysdate, e1.hiredate) Vechime,
CONCAT(d1.dname, '***') Dept_nume
FROM emp e1 full outer join dept d1 on e1.deptno = d1.deptno
WHERE MONTHS_BETWEEN(sysdate, e1.hiredate) > 12
ORDER BY Vechime;

-- varianta 3
SELECT e1.ename Nume,
SUBSTR(e1.ename, LENGTH(e1.ename)) Ultima_litera,
EXTRACT(DAY FROM e1.hiredate) Ziua,
MONTHS_BETWEEN(sysdate, e1.hiredate) Vechime,
regexp_replace(d1.dname, '$', '***') Dept_nume
FROM emp e1, dept d1
WHERE MONTHS_BETWEEN(sysdate, e1.hiredate) > 12 and e1.deptno = d1.deptno
ORDER BY Vechime;

4 .Sa se scrie o cerere SQL care face o lista cu numarul de aparitii ale ultimelor 2 litere din numele
angajatului(exact in ordinea literelor) care se regasesc in jobul angajatului(exact in acea ordine si
succesive). Antetul listei este urmatorul:
Nume_angajat, Job, Nr_aparitii
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL.
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE.

select
ename Nume_angajat,
job,
(length(job) - length(replace(job, substr(ename, length(ename)-1, 2), '')))/2 nr_aparitii
from emp;

select
ename Nume_angajat,
job,
(length(rtrim(job)) - length(replace(rtrim(job),substr(ename, length(ename)-1), '')))/2 nr_aparitii
from emp;

5. Pentru angajatii ce au aceeai paritate a lungimii numelui ca cea a sefului lor (daca nu au sef se
considera ca indeplinesc aceasta conditie), faceti o lista cu:

- numele departamentului in care este seful, scris cu litere mari (NUME_DEPT_SEF)

- cate luni complete au lucrat in firma (LUNI_LUCRATE_ANG)

- initiala numelui lor, ca litera mica (INITIALA_ANG)

- ultima cifra a venitului lor (ULTIMA_CIFRA_SALARIU)

Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL.

Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE.

--Metoda 1
SELECT
UPPER(dept.dname) as "NUME_DEPT_SEF",
TRUNC(MONTHS_BETWEEN(sysdate, emp.hiredate), 0) as "LUNI_LUCRATE_ANG",
LOWER(SUBSTR(emp.ename, 1, 1)) as "INITIALA_ANG",
MOD(emp.sal, 10) as "ULTIMA_CIFRA_SALARIU"
FROM
emp,
emp sef,
dept
WHERE
MOD(LENGTH(emp.ename),2) = MOD(LENGTH(sef.ename),2) AND
emp.mgr = sef.empno AND
sef.deptno = dept.deptno;

--Metoda2
SELECT
UPPER(dept.dname) as "NUME_DEPT_SEF",
TRUNC(MONTHS_BETWEEN(sysdate, emp.hiredate), 0) as "LUNI_LUCRATE_ANG",
LOWER(SUBSTR(emp.ename, 1, 1)) as "INITIALA_ANG",
MOD(emp.sal, 10) as "ULTIMA_CIFRA_SALARIU"
FROM
emp
inner join emp sef
on MOD(LENGTH(emp.ename),2) = MOD(LENGTH(sef.ename),2) AND emp.mgr = sef.empno
inner join dept
on sef.deptno = dept.deptno;

6. ​Sa se scrie o cerere SQL care face o lista cu data evaluarii angajatilor din departamentul 
de cercetare. Evaluarea va avea loc dupa 3 luni de la angajare, in ultima zi din saptamana 
respectiva. Antetul listei este urmatorul: 
Den_depart, Nume_angajat, Data_angajare, Data_evaluare 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 

-- metoda 1
select d.dname den_depart, a.ename nume_angajat, a.hiredate data_angajare,
next_day(add_months(a.hiredate, 3), 'SUNDAY') data_evaluare
from emp a, dept d
where a.deptno = d.deptno and d.dname like 'RESEARCH';

--metoda 2
select d.dname den_depart, a.ename nume_angajat, a.hiredate data_angajare,
next_day(add_months(a.hiredate, 3), 'SUNDAY') data_evaluare
from emp a
join dept d
on a.deptno = d.deptno
where d.dname like 'RESEARCH';

7. ​Pentru angajatii ce au aceeai paritate a lungimii numelui ca cea a sefului lor (daca nu au 
sef se considera ca indeplinesc aceasta conditie), faceti o lista cu: 
- numele departamentului in care este seful, scris cu litere mari (NUME_DEPT_SEF) 
- cate luni complete au lucrat in firma (LUNI_LUCRATE_ANG) 
- initiala numelui lor, ca litera mica (INITIALA_ANG) 
- ultima cifra a venitului lor (ULTIMA_CIFRA_SALARIU) 
Se se rezolve prin doua metode (scripturi) distincte folosind functii SQL. 
Testarea solutiilor se va face pe tabelele EMP, DEPT si SALGRADE. 

select
UPPER(dept.dname) as "NUME_DEPT_SEF",
TRUNC(MONTHS_BETWEEN(sysdate, emp.hiredate), 0) as "LUNI_LUCRATE_ANG",
LOWER(SUBSTR(emp.ename, 1, 1)) as "INITIALA_ANG",
MOD(emp.sal, 10) as "ULTIMA_CIFRA_SALARIU"
from
emp,
emp sef,
dept
where
mod(LENGTH(emp.ename),2) = mod(LENGTH(sef.ename),2)
and emp.mgr = sef.empno (+)
and sef.deptno = dept.deptno;

8. Sa se selecteze primele 3 litere din numele fiecarui angajat, venitul anual (incluzind si
comisionul) precum si o reprezentare grafica a venitului sub forma unui sir de caractere '$' , la
fiecare 10000 $ se va afisa un caracter '$' (de exemplu pentru un venit anual de 50000 $ se va afisa
sirul '$$$

).​Sevaconsideralimitainferioara,​ ​deexemplupentru2
​ 9000$​sevaafis
a

', la fel si pentru 21000$. Antetul listei este cod, venit, venit($) , lista este ordonata descrescator
dupa venitul anual.

-- Metoda 1:
select
SUBSTR(ename, 0, 3) as "cod",
12 * sal + nvl(comm, 0) as "venit",
RPAD(' ', floor((12 * sal + nvl(comm, 0)) / 10000) + 1, '$') as "venit($)"
from emp
order by 2 desc;

-- Metoda 2:
define anual = 12*sal+nvl(comm,0)
select
SUBSTR(ename, 0, 3) as "cod",
&anual as "venit",
RPAD(' ', floor((&anual) / 10000) + 1, '$') as "venit($)"
from emp
order by 2 desc;
undef anual

Test LAB 7
1. Sa se selecteze departamentele in care lucreaza cel putin 3 angajati care primesc
comision. Se va afisa numele departamentului, numarul de angajati din departament care
primesc comision, varianta salariilor din departament, deviatia standard a salariilor,
venitul maxim anual, suma veniturilor anuale precum si vechimea medie a angajatilor
exprimata in ani. Pentru varianta, deviatia standard si vechimea medie se vor afisa doar
doua zecimale. Lista are antetul departament, nr_ang, var, dev_std, venit_max, sum_venit,
vech_med.
dc vb urit ​macar nu s urit
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

Solutie:

define venit_anual = '12*e.sal+nvl(e.comm,0)'

select
d.dname "departament",
count(e.empno) "nr_ang",
round(variance(e.sal), 2) "var",
round(stddev(e.sal), 2) "dev_std",
max(&venit_anual) "venit_max",
sum(&venit_anual) "sum_venit",
round(avg(months_between(sysdate, e.hiredate)/12), 2) "vech_med"
from
dept d, emp e
where
e.deptno = d.deptno and nvl(e.comm,0) > 0
having
count(e.empno) >= 3
group by
d.dname;

undefine venit_anual

2. Sa se afiseze o lista in care angajatii primesc o prima in functie de grila de salariu. Prima
se calculeaza astfel:

● - salariul minim din firma, daca salariatul are gradul 1 in girla


● - media corespunzatoare gradului, daca are gradul 2 sau 3 (media se calculeaza pe baza
"losal" si "hisal")
● - salariul mediu din firma rotunjit la doua zecimale, daca are gradul 4
● - c*sal_maxim_din_firma unde c este o variabila citita de la tastatura, daca are gradul 5

Lista are antetul: nume, grad,prima.

Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

Solutie:
ACCEPT c CHAR 'INTRODU VARIABILA C: '

SELECT E.ENAME NUME, ESAL.GRADE GRAD,


CASE ESAL.GRADE
WHEN 1 THEN MIN(E.SAL)
WHEN 2 THEN (ESAL.LOSAL + ESAL.HISAL) / 2
WHEN 3 THEN (ESAL.LOSAL + ESAL.HISAL) / 2
WHEN 4 THEN ROUND(AVG(E.SAL), 2)
WHEN 5 THEN to_number(&c) * MAX(E.SAL)
END PRIMA
FROM EMP E
INNER JOIN SALGRADE ESAL ON
E.SAL >= ESAL.LOSAL AND
E.SAL <= ESAL.HISAL
GROUP BY E.ENAME, E.SAL, ESAL.GRADE, ESAL.LOSAL, ESAL.HISAL
ORDER BY 1;

3.​Sa se afiseze numele departamentelor in care lucreaza cel putin doi angajati care au cel 
putin gradul g de salarizare, unde g este o variabila citita de la tastatura. Se va afisa numele 
departamentului, orasul si numarul de angajati care respecta criteriile de mai sus. Antetul 
listei este departament, oras, nr_ang. Se va ordona descrescator dupa coloana nr_ang. 
Solutie:

-- varianta 1

-- varianta 2

select
d.dname departament,
d.loc oras,
count(e.empno) nr_ang
FROM salgrade s, emp e
NATURAL JOIN dept d
WHERE s.grade >= &g AND e.sal >= s.losal AND e.sal <= s.hisal
GROUP BY d.dname, d.loc
HAVING count(e.empno) >= 2
ORDER BY nr_ang DESC;

4. ​Sa se afiseze, pentru toti angajatii departamentului RESEARCH, o lista care sa contina o 
apreciere a vechimii angajatului precum si numarul de subordonati direct ai angajatului 
respectiv. 
Aprecierea vechimii se va face astfel : 
- Daca au venit in firma inainte de 31 decembrie 1980, atunci vechime=’FOARTE VECHI’ 
- Daca au venit in firma intre anii 1981 si 1986, atunci vechime=’VECHI’ 
- Daca au venit in firma dupa 1986, atunci vechime=’RECENT’ 
Lista va afisa si angajatii care nu au subordonati. 
Antetul listei este urmatorul: 
Nume_angajat, Salariu, Apreciere_vechime, Nr_subordonati 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
select a1.ename Nume_angajat, 
a1.sal Salariu, 
case 
when a1.hiredate <= to_date('31121980', 'DD-MM-YYYY') then 'FOARTE_VECHI' 
when a1.hiredate <= to_date('01011986', 'DD-MM-YYYY') then 'RECENT' 
else 'VECHI' 
end Apreciere_vechime, 
count (a2.empno) Nr_subordonati 
from 
emp a1 
join emp a2 on a1.empno=a2.mgr(+) 
join dept d on a1.deptno=d.deptno and d.dname='RESEARCH' 
group by a1.ename, a1.sal, a1.hiredate; 
 
 
5. ​Afisati, pentru toti angajatii din tabela emp/angajati: 
- salariul formatat ca sir cu 2 zecimale dupa virgula si cu un dolar in fata pentru toti 
angajatii cu gradul salarial > 3, 
- luna angajarii in format string daca au gradul salarial < 3, 
- ultimele 3 caractere din functie daca au gradul salarial egal cu 3. 
Hint: Folositi functia SIGN. 
Antetul listei va fi urmatorul: 
Nume_ang, Salariu_ang, Grad_salariu_ang, Calcul. 
Ordonati dupa coloana calculata. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
 
select 
a.ename "Nume_ang", 
a.sal "Salariu_ang", 
g.grade "Grad_salariu_ang", 
(case sign(g.grade - 3) 
when 1 then to_char(a.sal, '$9999.99') 
when -1 then to_char(a.hiredate, 'MONTH') 
else substr(a.job, length(a.job) - 2, 3) 
end) "Calcul" 
from emp a 
join salgrade g 
on a.sal between g.losal and g.hisal 
order by 4; 
 
6.Sa se afiseze, pentru toti angajatii departamentului RESEARCH, o lista care sa contina o 
apreciere a vechimii angajatului precum si numarul de subordonati direct ai angajatului 
respectiv. 
Aprecierea vechimii se va face astfel : 
- Daca au venit in firma inainte de 31 decembrie 1980, atunci vechime=’FOARTE VECHI’ 
- Daca au venit in firma intre anii 1981 si 1986, atunci vechime=’VECHI’ 
- Daca au venit in firma dupa 1986, atunci vechime=’RECENT’ 
Lista va afisa si angajatii care nu au subordonati. 
Antetul listei este urmatorul: 
Nume_angajat, Salariu, Apreciere_vechime, Nr_subordonati 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
 
select 
e.ename "Nume_angajat", 
e.sal "Salariu", 
case when e.hiredate < '31-DEC-80' then 'FOARTE VECHI' 
when extract(year from e.hiredate) between 1981 and 1986 then 'VECHI' 
when extract(year from e.hiredate) > 1986 then 'RECENT' 
end "Apreciere_vechime", 
count(e1.empno) "Nr_subordonati" 
from emp e 
left outer join emp e1 
on e.empno = e1.mgr 
join dept d 
on e.deptno = d.deptno and d.dname like 'RESEARCH' 
group by 
e.ename, e.sal, e.hiredate; 
 
 
 
7. Afisati, pentru toti angajatii din tabela emp/angajati: 

- salariul formatat ca sir cu 2 zecimale dupa virgula si cu un dolar in fata pentru toti 
angajatii cu gradul salarial > 3, 

- luna angajarii in format string daca au gradul salarial < 3, 

- ultimele 3 caractere din functie daca au gradul salarial egal cu 3. 

Hint: Folositi functia SIGN. 

Antetul listei va fi urmatorul: 

Nume_ang, Salariu_ang, Grad_salariu_ang, Calcul. 

Ordonati dupa coloana calculata. 

SELECT 

e.ename "Nume_ang", 

e.sal "Salariu_ang", 

g.grade "Grad_salariu_ang", 

CASE 

  WHEN g.grade > 3 THEN TO_CHAR(e.sal, '$99999.99') 

  WHEN g.grade < 3 THEN TO_CHAR(e.hiredate, 'MONTH') 

  WHEN g.grade = 3 THEN SUBSTR(e.job, -3, 3) 

END "Calcul" 
FROM 

emp e 

JOIN salgrade g ON e.sal BETWEEN g.losal AND g.hisal 

ORDER BY "Calcul"; 

 
 
 

Test LAB 8
1. Afisati angajatii al caror grad salarial se regaseste printre gradele salariale maxime ale
angajatilor, pentru fiecare departament si an al angajarii.

Hint: gruparea se face dupa departament si anul angajarii

Antetul listei este urmatorul: Nume_angajat, Nume_departament, Grad_salarial, An_angajare.

Sortati dupa numele departamentului si anul angajarii.

Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

Solutie:

select
e.ename "Nume_angajat",
d.dname "Nume_departament",
g.grade "Grad_salarial",
to_char(e.hiredate, 'YYYY') "An_angajare"
from
emp e
join salgrade g
on e.sal between g.losal and g.hisal
join dept d
on e.deptno = d.deptno
where
g.grade in (select
max(g1.grade)
from
salgrade g1
join emp e1
on e1.sal between g1.losal and g1.hisal
join dept d1
on e1.deptno = d1.deptno
group by
d1.deptno)
and
g.grade in (select
max(g1.grade)
from
salgrade g1
join emp e1
on e1.sal between g1.losal and g1.hisal
join emp e2
on to_char(e1.hiredate, 'YYYY') = to_char(e2.hiredate, 'YYYY')
group by
to_char(e2.hiredate, 'YYYY'))
order by
d.dname, to_char(e.hiredate, 'YYYY');

2. Sa se scrie o cerere SQL care face o lista cu angajatii care nu au primit comision si 
care primesc un bonus la salariu aplicand urmatoarele criterii: 
- Daca salariu_angajat < salariu_mediu_departament_propriu =>  
  bonus = sal_min_ departament_propriu 
- Daca salariu_angajat >= salariu_mediu_departament_propriu =>  
  bonus = sal_max_ departament_propriu 
- Directorii si presedintele companiei nu primesc bonus. 
Antetul listei este urmatorul: 
Den_depart, Nume_ang, Job, Salariu_ang, Comision, Sal_mediu_dep, Bonus 
Salariul mediu pe departament se afiseaza fara zecimale. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si 
SALGRADE. 
Solutie:
select
d.dname Den_depart,
e.ename Nume_ang,
e.job Job,
e.sal Salariu_ang,
e.comm Comision,
round((select avg(sal) from emp where e.deptno = deptno), 0) Sal_mediu_dep,
case
when e.job = 'MANAGER' or e.job = 'PRESIDENT'
then null
when e.sal < (select avg(sal) from emp where e.deptno = deptno)
then (select min(sal) from emp where e.deptno = deptno)
when e.sal >= (select avg(sal) from emp where e.deptno = deptno)
then (select max(sal) from emp where e.deptno = deptno)
end Bonus
from emp e, dept d
where (e.comm = 0 or e.comm is null) and e.deptno = d.deptno;

3. ​Sa se calculeze, pentru fiecare angajat ce are, in departamentul sau, cel putin doi angajati 
cu un salariu mai mic decat el si care a venit in firma dupa seful sau direct: vechimea in ani 
(valoare intreaga), gradul salarial si diferenta dintre salariul sefului sau si salariul sau. 
Antetul listei de afisat trebuie sa fie : 
Nume angajat, Denumire departament, Ani vechime, Grad, Diferenta salariu sef  
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 

select
a.ename "Nume angajat",
d.dname "Denumire departament",
to_char(sysdate, 'YYYY') - to_char(a.hiredate, 'YYYY') "Ani vechime",
g.grade "Grad",
a2.sal - a.sal "Diferenta salariu sef"
from
emp a
join dept d
on d.deptno = a.deptno
join emp a2
on a2.empno = a.mgr
join salgrade g
on a.sal between g.losal and g.hisal
where
(select count(*)
from emp a1
where
a1.deptno = a.deptno and a.sal > a1.sal) >= 2
and
a.hiredate > a2.hiredate;

4. Sa se selecteze numele angajatului, numele departamentului in care lucreaza, functia si salariul, pentru
angajatii care au salariul maxim pentru functia lor in departametul in care lucreaza.
Ordonati dupa numele departamentului, functie si numele angajatului.

Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE.

SELECT
e1.ename "Nume ang",
d.dname "Nume dept",
e1.job "Functie",
e1.sal "Salariu"
FROM
emp e1
join dept d
on d.deptno = e1.deptno
WHERE
e1.sal = (SELECT
max(e2.sal)
FROM
emp e2
WHERE
e2.deptno = e1.deptno and e1.job = e2.job)
ORDER BY
d.dname, e1.job, e

5. ​Sa se selecteze numele angajatului, numele departamentului in care lucreaza, functia si 
salariul, pentru angajatii care au salariul maxim pentru functia lor in departametul in care 
lucreaza. 
Ordonati dupa numele departamentului, functie si numele angajatului. 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
select a.ename "nume_ang", d.dname "nume_dep", a.job "functie", a.sal "salariu"
from emp a
join dept d
on a.deptno = d.deptno
where a.sal = (select max(sal)
from emp
where deptno = a.deptno and job = a.job)
order by 2, 3, 1;

6. ​Sa se scrie o singura cerere care afiseaza o lista cu: 


- Numele angajatului (Nume_Angajat) 
- Numele sefului (Nume_Sef) 
- Grila salariala (Grad salarial) a angajatului (Grila_Angajat) 
- Prima angajatului (Prima_Angajat) 
Prima se calculeaza dupa urmatoarea formula: 
- daca angajatul are salariul peste media pe departamentul lui: prima=Grila_Angajat * 
Salariu 
- altfel, prima= Grila_Angajat * (venit sef) 
Observatii: 
- Rotunjiti primele angajatilor 
- King nu are Sef 
Se va utiliza, pentru testare, baza de date formata din tabelele EMP, DEPT si SALGRADE. 
 
select 
ang.ename "Nume_Angajat", 
mng.ename "Nume_sef", 
grd.grade "Grila_Angajat", 
ROUND( 
CASE WHEN ang.sal > (SELECT AVG(sal) FROM emp WHERE deptno = ang.deptno) 
THEN grd.grade * ang.sal 
ELSE grd.grade * (mng.sal + NVL(mng.comm,0)) 
END) "Prima_Angajat" 
FROM  
emp ang 
LEFT OUTER JOIN emp mng ON ang.mgr = mng.empno 
INNER JOIN salgrade grd ON ang.sal BETWEEN grd.losal AND grd.hisal; 
7. Sa se calculeze, pentru fiecare angajat ce are, in departamentul sau, cel putin doi
angajati cu un salariu mai mic decat el si care a venit in firma dupa seful sau direct:
vechimea in ani (valoare intreaga), gradul salarial si diferenta dintre salariul sefului sau si
salariul sau.
Antetul listei de afisat trebuie sa fie :
Nume angajat, Denumire departament, Ani vechime, Grad, Diferenta salariu sef  

SELECT
e1.ename as "Nume angajat",
d.dname as "Denumire departament",
EXTRACT(YEAR FROM sysdate) - EXTRACT(YEAR FROM e1.hiredate) as "Ani
vechime",
g.grade as "Grad",
sef.sal - e1.sal as "Diferenta salariu sef"
FROM
emp e1
INNER JOIN dept d
ON d.deptno = e1.deptno
INNER JOIN emp sef
ON sef.empno = e1.mgr
INNER JOIN salgrade g
ON e1.sal >= g.losal AND e1.sal <= g.hisal
WHERE
(SELECT COUNT(ALL e2.ename) FROM emp e2
WHERE e2.deptno = e1.deptno AND e1.sal > e2.sal) >= 2 AND e1.hiredate >
sef.hiredate; 

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