Advertisement
Guest User

Untitled

a guest
Feb 25th, 2020
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.17 KB | None | 0 0
  1. /* Extensii SQL pentru procesari analitice in Oracle */
  2.  
  3. /* EXEMPLE */
  4. -- FUNCTIILE RANK() SI DENSE_RANK()
  5. -- clasamentul angajatilor dupa salarii
  6. SELECT ename, sal, RANK() OVER (ORDER BY sal DESC) position
  7. FROM emp;
  8.  
  9. SELECT ename, sal, DENSE_RANK() OVER (ORDER BY sal DESC) position
  10. FROM emp;
  11.  
  12. -- clasificare pe partitii
  13. -- afisarea angajatilor pe departamente
  14. SELECT deptno, ename, sal, DENSE_RANK() OVER (PARTITION BY deptno ORDER BY sal DESC) posdept
  15. FROM emp;
  16.  
  17. -- clasificare dupa expresii multiple
  18. -- clasamentul salariatilor dupa salariu si dupa data angajarii
  19. SELECT deptno, ename, sal, hiredate, RANK() OVER (PARTITION BY deptno ORDER BY sal DESC, hiredate ASC) posdept
  20. FROM emp;
  21.  
  22. -- clasificare dupa partitii multiple
  23. -- clasamentul angajatilor dupa salarii, clasament grupat dupa departament si dupa job
  24. SELECT deptno, job, ename, sal,
  25. RANK() OVER (PARTITION BY deptno ORDER BY sal DESC) posdept,
  26. RANK() OVER (PARTITION BY job ORDER BY sal DESC) posjob
  27. FROM emp;
  28.  
  29. -- FUNCTIA CUME_DIST()
  30. -- distributia salariilor angajatilor
  31. SELECT ename, sal,
  32. ROUND(CUME_DIST() OVER (ORDER BY sal DESC), 2) cume_dist_sal
  33. FROM emp;
  34.  
  35. -- distributia salariilor pe departamente
  36. SELECT deptno, ename, sal,
  37. ROUND(CUME_DIST() OVER (PARTITION BY deptno ORDER BY sal DESC), 2) cume_dist_sal_dept
  38. FROM emp;
  39.  
  40. -- FUNCTIA PERCENT_RANK()
  41. -- distributiile pozitionale ale salariilor pe departamente
  42. SELECT deptno, ename, sal,
  43. ROUND(PERCENT_RANK() OVER (PARTITION BY deptno ORDER BY sal DESC), 2) percent_rank_sal_dept
  44. FROM emp;
  45.  
  46. -- FUNCTIILE NTILE() SI ROW_NUMBER()
  47. -- salariile descrescator, impartite in 4 categorii
  48. SELECT deptno, ename, sal,
  49. NTILE(4) OVER (ORDER BY sal DESC) ntile4
  50. FROM emp;
  51.  
  52. -- salariile descrescator, partitionate dupa departament si impartite in cate 2 buchete
  53. SELECT deptno, ename, sal,
  54. NTILE(2) OVER (PARTITION BY deptno ORDER BY sal DESC) ntile2_deptno
  55. FROM emp;
  56.  
  57. -- salariile angajatilor partitionate dupa departamente, impreuna cu o coloana de numerotare
  58. -- care se reseteaza dupa fiecare partitie
  59. SELECT deptno, ename, sal,
  60. ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY sal DESC) nrcrt
  61. FROM emp;
  62.  
  63. /* EXERCITII */
  64. -- 1
  65. SELECT d.dname, e.ename, e.hiredate, e.job,
  66. RANK() OVER (ORDER BY e.hiredate ASC) clasament -- pozitia se afla ordonand dupa data angajarii si calculand "RANK()"-ul
  67. FROM emp e JOIN dept d ON e.deptno = d.deptno;
  68.  
  69. -- 2
  70. SELECT deptno AS "DeptAvgSal", job AS "JobAvgSal",
  71. ROUND(AVG(sal), 2) AS "AvgSal",
  72. RANK() OVER (PARTITION BY deptno ORDER BY ROUND(AVG(sal), 2) DESC) pozitie_dept -- pozitia in cadrul departamentului
  73. -- folosim "PARTITION BY deptno" pentru a face clasamentul mediilor salariale pe departamente, si nu global
  74. -- adica "pozitie_dept" este relativa la numarul departamentului = campul DeptAvgSal
  75. FROM emp
  76. GROUP BY ROLLUP(deptno, job); -- linii totalizatoare pentru departament si job
  77.  
  78. -- 3
  79. SELECT deptno AS "DeptAvgSal", job AS "JobAvgSal",
  80. ROUND(AVG(sal), 2) AS "AvgSal",
  81. RANK() OVER (PARTITION BY deptno ORDER BY ROUND(AVG(sal), 2) DESC) pozitie_dept,
  82. RANK() OVER (PARTITION BY job ORDER BY ROUND(AVG(sal), 2) DESC) pozitie_job -- pozitia in cadrul job-ului
  83. -- partitionam dupa job, iar pentru fiecare "job" fixat, se ordoneaza mediile salariale si se calculeaza pozitia in ierarhie
  84. FROM emp
  85. GROUP BY ROLLUP(deptno, job);
  86.  
  87. -- 4
  88. SELECT *
  89. FROM (SELECT DENSE_RANK() OVER (ORDER BY sal + NVL(comm, 0) * sal DESC) pozitie_venit,
  90. -- ordonam dupa venit (salariu + comision) si calculam DENSE_RANK(), si nu RANK()
  91. -- pentru ca vrem ca duplicatele sa fie tratate ca aflandu-se pe acelasi nivel ierarhic
  92. -- (SCOTT si FORD sunt pe acelasi loc, nu ocupa 2 locuri diferite in ierarhie)
  93. ename, sal, comm, sal + NVL(comm, 0) * sal AS "Venit"
  94. FROM emp)
  95. -- dorim primele 10 inregistrari: folosim o subinterogare, din care preluam tot, cu conditia ca pozitia calculata sa fie <= 10
  96. -- nu avem cum folosi conditia din WHERE-ul exterior in SELECT-ul din interior, deoarece alias-ul "pozitie_venit" nu este cunoscut decat in exterior!
  97. WHERE pozitie_venit <= 10;
  98.  
  99. -- 5
  100. SELECT *
  101. FROM (SELECT DENSE_RANK() OVER (ORDER BY sal + NVL(comm, 0) * sal DESC) pozitie_venit,
  102. ROUND(PERCENT_RANK() OVER (ORDER BY sal + NVL(comm, 0) * sal DESC), 2) distributie_venit,
  103. -- distributia veniturilor = functia PERCENT_RANK() in loc de RANK() / DENSE_RANK()
  104. ename, sal, comm, sal + NVL(comm, 0) * sal AS "Venit"
  105. FROM emp)
  106. WHERE pozitie_venit <= 10;
  107.  
  108. -- 6
  109. SELECT NTILE(4) OVER (ORDER BY sal + NVL(comm, 0) * sal DESC) nr_crt, -- numarul buchetului
  110. -- impartim in 4 buchete folosind functia NTILE()
  111. DENSE_RANK() OVER (ORDER BY sal + NVL(comm, 0) * sal DESC) pozitie_venit, -- pozitia nivelului de venit
  112. ename, sal, sal + NVL(comm, 0) * sal AS "Venit"
  113. FROM emp;
  114.  
  115. -- 7
  116. SELECT ch.channel_desc, SUM(s.amount_sold) AS "Vanzari canal de distributie",
  117. RANK() OVER(ORDER BY SUM(s.amount_sold) DESC) pozitie
  118. FROM sales s JOIN channels ch ON (s.channel_id = ch.channel_id)
  119. -- JOIN-uri pentru a afla informatiile suplimentare necesare la filtrare si afisare
  120. JOIN times t ON (s.time_id = t.time_id)
  121. JOIN customers cust ON (s.cust_id = cust.cust_id)
  122. WHERE t.calendar_month_desc IN ('2000-09', '2000-10') -- filtrarile din enunt
  123. AND cust.country_id = 'US'
  124. GROUP BY ch.channel_desc; -- vanzarile trebuie grupate pe canale de distributie
  125.  
  126. -- 8
  127. SELECT ch.channel_desc, t.calendar_month_desc, SUM(s.amount_sold) AS "Total vanzari",
  128. RANK() OVER(PARTITION BY ch.channel_desc ORDER BY SUM(s.amount_sold) DESC) pozitie_canal_distributie
  129. -- partitionam dupa canalul de distributie, apoi pentru fiecare canal fixat, ordonam dupa valoarea vanzarilor ca sa aflam pozitia relativa
  130. FROM sales s JOIN channels ch ON (s.channel_id = ch.channel_id)
  131. JOIN times t ON (s.time_id = t.time_id)
  132. WHERE t.calendar_month_desc IN ('2000-08', '2000-09', '2000-10', '2000-11')
  133. GROUP BY ch.channel_desc, t.calendar_month_desc;
  134.  
  135. -- 9
  136. SELECT ch.channel_desc, t.calendar_month_desc, SUM(s.amount_sold) AS "Total vanzari",
  137. RANK() OVER(PARTITION BY ch.channel_desc ORDER BY SUM(s.amount_sold) DESC) pozitie_canal_distributie,
  138. RANK() OVER(PARTITION BY t.calendar_month_desc ORDER BY SUM(s.amount_sold) DESC) pozitie_luna
  139. -- pozitia in cadrul lunii = partitionam dupa luna si ordonam partitiile rezultate dupa valoarea vanzarilor, pentru a afla pozitia relativa din luna respectiva
  140. FROM sales s JOIN channels ch ON (s.channel_id = ch.channel_id)
  141. JOIN times t ON (s.time_id = t.time_id)
  142. WHERE t.calendar_month_desc IN ('2000-08', '2000-09', '2000-10', '2000-11')
  143. GROUP BY ch.channel_desc, t.calendar_month_desc;
  144.  
  145. -- 10
  146. SELECT ch.channel_desc, cust.country_id, SUM(s.amount_sold) AS "Total vanzari",
  147. RANK() OVER(PARTITION BY ch.channel_desc ORDER BY SUM(s.amount_sold) DESC) pozitie_grup
  148. -- pozitionare in cadrul canalului de distributie = facem partitionare dupa canalul de distributie
  149. -- si pentru fiecare inregistrare pentru un canal fixat se calculeaza rangul in acea partitie
  150. FROM sales s JOIN channels ch ON (s.channel_id = ch.channel_id)
  151. JOIN times t ON (s.time_id = t.time_id)
  152. JOIN customers cust ON (s.cust_id = cust.cust_id)
  153. WHERE ch.channel_desc IN ('Direct Sales', 'Internet') -- filtrarile cerute
  154. AND t.calendar_month_desc = '2000-09'
  155. AND cust.country_id IN ('UK', 'US', 'JP')
  156. GROUP BY CUBE(ch.channel_desc, cust.country_id);
  157. -- totalul vanzarilor pe canalul de distributie si pe tara + linii de subtotaluri pentru combinarea celor 2 dimensiuni
  158. -- CUBE() in loc de ROLLUP() pentru ca trebuie toate combinatiile intre dimensiuni
  159.  
  160. -- 11
  161. SELECT *
  162. FROM (
  163. SELECT cust.country_id, SUM(s.amount_sold) AS "Total vanzari",
  164. RANK() OVER(ORDER BY SUM(s.amount_sold) DESC) pozitie
  165. -- top vanzari = ordonare descrescatoare in functie de suma valorilor vanzarilor
  166. -- apoi calcul de rang pe aceasta ordonare
  167. FROM sales s JOIN times t ON (s.time_id = t.time_id)
  168. JOIN customers cust ON (s.cust_id = cust.cust_id)
  169. WHERE t.calendar_month_desc = '2000-09'
  170. GROUP BY cust.country_id -- trebuie grupate rezultatele pentru ca folosim functia agregat SUM(),
  171. -- iar afisarea trebuie facuta in functie de tara
  172. -- din interogarea interioara rezulta o lista cu toate tarile ordonate dupa vanzari
  173. -- nu putem afisa doar primele 5 inregistrari in acest SELECT, deoarece alias-ul "pozitie" nu este vizibil in acelasi
  174. -- SELECT in care este creat
  175. )
  176. -- se face un SELECT exterior din tabelul rezultat, din care selectam toate coloanele si filtram dupa coloana alias "pozitie",
  177. -- care devine vizibila de aceasta data
  178. WHERE pozitie <= 5;
  179.  
  180. -- 12
  181. SELECT t.calendar_month_desc, SUM(s.amount_sold) AS "Total vanzari",
  182. NTILE(4) OVER (ORDER BY SUM(s.amount_sold) DESC) pozitie_buchet
  183. -- impartire in 4 buchete = functia NTILE(), dupa suma vanzarilor = ordonare dupa SUM(...)
  184. FROM sales s JOIN times t ON (s.time_id = t.time_id)
  185. JOIN products p ON (s.prod_id = p.prod_id)
  186. WHERE t.calendar_year = '1999' -- filtrarile cerute
  187. AND p.prod_category = 'Men'
  188. GROUP BY t.calendar_month_desc; -- se grupeaza din acelasi motiv ca la 11, folosim o functie agregat SUM()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement