Skip to content

Commit c5fcc6a

Browse files
committed
completed till Framing window function
1 parent 8ded6c6 commit c5fcc6a

File tree

2 files changed

+216
-5
lines changed

2 files changed

+216
-5
lines changed

Complete SQL & Databases - ZTM/06_Advanced_SQL.sql

Lines changed: 216 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ JOIN departments d ON d.dept_no = de.dept_no
1212
GROUP BY d.dept_no
1313
ORDER BY 1;
1414

15+
/*------------------------------------------------------------------------------------------------------------*/
1516

1617
/************ 2) HAVING Keyword *************/
1718
/*
@@ -45,6 +46,7 @@ GROUP BY d.dept_name
4546
HAVING COUNT(e.emp_no) > 25000
4647
ORDER BY 1;
4748

49+
/*------------------------------------------------------------------------------------------------------------*/
4850

4951
/********** 3) Ordering Group Data **********/
5052
SELECT d.dept_name AS "Department Name" ,COUNT(e.emp_no) AS "Number Of Employee"
@@ -56,13 +58,17 @@ HAVING COUNT(e.emp_no) > 25000
5658
ORDER BY 2 DESC;
5759

5860

59-
/********* 4) Group by Mental Model ***********/
61+
/********* 4) GROUP BY Mental Model ***********/
62+
6063
/* What are the 8 employees who got the most salary bumps? */
6164
-- SELECT e.emp_no, CONCAT(e.first_name, e.last_name) AS "Name", s.salary, s.from_date, s.to_date
6265
SELECT emp_no, MAX(from_date)
6366
FROM salaries
6467
GROUP BY emp_no;
6568

69+
70+
/*------------------------------------------------------------------------------------------------------------*/
71+
6672
/*********** 5) GROUPING SETS**********/
6773

6874
/******* UNION / UNION ALL *********/
@@ -81,20 +87,25 @@ GROUP BY emp_no;
8187
*/
8288
SELECT NULL AS "prod_id", sum(ol.quantity)
8389
FROM orderlines AS ol
90+
8491
UNION
92+
8593
SELECT prod_id AS "prod_id", sum(ol.quantity)
8694
FROM orderlines AS ol
8795
GROUP BY prod_id
8896
ORDER BY prod_id DESC;
8997

98+
/*------------------------------------------------------------------------------------------------------------*/
99+
90100
/*********** GROUPING SETS ***********/
91101
/*
92102
A Subclause of GROUP BY that allows you to define multiple grouping
93103
It is very useful when we want to combine multiple grouping
94104
*/
95105

96-
-- same result as using above UNION code
97-
SELECT NULL AS "prod_id", sum(ol.quantity)
106+
-- same result as using above UNION code, but in same query
107+
-- here we are combining Two Sets (one for getting Total, one for per each product)
108+
SELECT prod_id, sum(ol.quantity)
98109
FROM orderlines AS ol
99110
GROUP BY
100111
GROUPING SETS(
@@ -103,13 +114,213 @@ GROUP BY
103114
)
104115
ORDER BY prod_id DESC;
105116

117+
106118
/* we can add in multiple groups as we need */
107-
SELECT NULL AS "prod_id", orderlineid, sum(ol.quantity)
119+
SELECT prod_id, orderlineid, sum(ol.quantity)
108120
FROM orderlines AS ol
109121
GROUP BY
110122
GROUPING SETS(
111123
(),
112124
(prod_id),
113125
(orderlineid)
114126
)
115-
ORDER BY prod_id DESC, orderlineid DESC;
127+
ORDER BY prod_id DESC, orderlineid DESC;
128+
129+
/*------------------------------------------------------------------------------------------------------------*/
130+
131+
/************ GROUPING SETS for info from High Level to Details Level ***********/
132+
133+
SELECT
134+
EXTRACT(YEAR FROM orderdate) AS "YEAR",
135+
EXTRACT(MONTH FROM orderdate) AS "MONTH",
136+
EXTRACT(DAY FROM orderdate) AS "DAY",
137+
SUM(quantity)AS "TOTAL QUANTITY"
138+
FROM orderlines
139+
GROUP BY
140+
GROUPING SETS(
141+
(EXTRACT(YEAR FROM orderdate)), -- yearly
142+
(EXTRACT(MONTH FROM orderdate)), -- monthly
143+
(EXTRACT(DAY FROM orderdate)), -- daily
144+
(
145+
EXTRACT(YEAR FROM orderdate), -- month and year
146+
EXTRACT(MONTH FROM orderdate)
147+
),
148+
(
149+
EXTRACT(MONTH FROM orderdate), -- month and day
150+
EXTRACT(DAY FROM orderdate)
151+
),
152+
(
153+
EXTRACT(YEAR FROM orderdate), -- year, month and day
154+
EXTRACT(MONTH FROM orderdate),
155+
EXTRACT(DAY FROM orderdate)
156+
),
157+
() -- nothing in particular (TOTAL AMOUNT)
158+
)
159+
ORDER BY 1,2,3;
160+
161+
/*------------------------------------------------------------------------------------------------------------*/
162+
163+
/************ 6) ROLLUP ***************/
164+
165+
/* roll up can provide a very similar result as above using grouping sets, but with less code */
166+
SELECT
167+
EXTRACT(YEAR FROM orderdate) AS "YEAR",
168+
EXTRACT(MONTH FROM orderdate) AS "MONTH",
169+
EXTRACT(DAY FROM orderdate) AS "DAY",
170+
SUM(quantity)AS "TOTAL QUANTITY"
171+
FROM orderlines
172+
GROUP BY
173+
ROLLUP(
174+
EXTRACT(YEAR FROM orderdate),
175+
EXTRACT(MONTH FROM orderdate),
176+
EXTRACT(DAY FROM orderdate)
177+
)
178+
ORDER BY 1,2,3;
179+
180+
/*------------------------------------------------------------------------------------------------------------*/
181+
182+
/******************** 8/9) WINDOW Functions ******************/
183+
/*
184+
Window functions CREATE a NEW COLUMN based on functions performed on a SUBSET or "WINDOW" of the data.
185+
186+
window_function(agr1, agr2) OVER(
187+
[PARTITION BY partition_expression]
188+
[ORDER BY sort_expression [ASC | DESC] [NULLS {FIRST | LAST}]]
189+
)
190+
*/
191+
192+
-- Here we can see in the result that max salary is 158,220. Because query returns all data, then LIMIT say cut it off for 100 rows only.
193+
-- That's why OVER() is calculated on the window or subset of data (in this case the entire data were returned).
194+
SELECT *,
195+
MAX(salary) OVER()
196+
FROM salaries
197+
LIMIT 100;
198+
199+
-- in this case, the maximum salary is 69,999. Because of WHERE conditions, the data were filtered out.
200+
-- and OVER() is using on that subset or window of the returned data (in this case the results of WHERE filtered data).
201+
SELECT
202+
*,
203+
MAX(salary) OVER()
204+
FROM salaries
205+
WHERE salary < 70000
206+
ORDER BY salary DESC;
207+
208+
209+
/******************** 10) PARTITON BY ******************/
210+
/*
211+
Divide Rows into Groups to apply the function against (Optional)
212+
*/
213+
214+
/* Employee salary compairing average salary of departments */
215+
SELECT
216+
s.emp_no, s.salary,d.dept_name,
217+
AVG(s.salary)
218+
OVER(
219+
PARTITION BY(d.dept_name)
220+
)
221+
FROM salaries s
222+
JOIN dept_emp de ON s.emp_no = de.emp_no
223+
JOIN departments d ON d.dept_no = de.dept_no;
224+
225+
226+
/******************** 11) ORDER BY ******************/
227+
/*
228+
ORDER BY changes the FRAME of the window
229+
It tells SQL to take into account of everything before up until to this point (becoming Cumulative)
230+
*/
231+
-- against the window of entire data
232+
SELECT emp_no,
233+
COUNT(salary) OVER()
234+
FROM salaries;
235+
236+
-- using PARTION BY
237+
-- Counting salary by each unique emp_no partion
238+
SELECT emp_no,
239+
COUNT(salary) OVER(
240+
PARTITION BY(emp_no)
241+
)
242+
FROM salaries;
243+
244+
245+
-- using ORDER BY
246+
-- Count number are becoming Cumulative
247+
SELECT emp_no,
248+
COUNT(salary) OVER(
249+
ORDER BY emp_no
250+
)
251+
FROM salaries;
252+
253+
254+
/********************************* FRAME Clause *******************************************************/
255+
/*
256+
When using Frame clause in a window function, we can create a SUB-RANGE or FRAME
257+
258+
For example: when we use ORDER BY, we look at the PARTATIONED data in a different len (FRAME).
259+
260+
NOTE:
261+
Without ORDER BY, by default the framing is usually ALL PARTITION ROWs (Entire Window)
262+
With ORDER BY, by default the framing is usually everything before the CURRENT ROW AND the CURRENT ROW (Cumulatively)
263+
264+
|----------------------------------------------------------------------------------------------------
265+
| Keys | Meaning |
266+
|---------------------------------------|-----------------------------------------------------------|
267+
| ROWS or RANGE | Whether you want to use a RANGE or ROWS as a FRAME |
268+
| PRECEDING | Rows Before the CURRENT ONE |
269+
| FOLLOWING | Rows After the CURRENT ONE |
270+
| UNBOUNDED PRECEDING or FOLLOWING | Returns All Before and After |
271+
| CURRENT ROW | Your Current Row |
272+
-----------------------------------------------------------------------------------------------------
273+
*/
274+
275+
-- In this case, we can see that every salary is unique. Because we are using ORDER BY, each row is cumulativly
276+
-- counted within the partition of each employee's window. As a result, it like like 1, (1+1 becomes 2), etc.
277+
SELECT emp_no,
278+
salary,
279+
COUNT(salary) OVER(
280+
PARTITION BY emp_no
281+
ORDER BY salary
282+
)
283+
FROM Salaries;
284+
285+
286+
-- This one returns the same results as using PARTION BY only. The reason is we are looking at the data through the lends of Range.
287+
-- For range using unbounded precedning and following, we are comparing against data with the entire data within that Partition.
288+
SELECT emp_no,
289+
salary,
290+
COUNT(salary) OVER(
291+
PARTITION BY emp_no
292+
ORDER BY salary
293+
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
294+
)
295+
FROM Salaries;
296+
297+
-- same reults as RANGE results
298+
SELECT emp_no,
299+
salary,
300+
COUNT(salary) OVER(
301+
PARTITION BY emp_no
302+
ORDER BY salary
303+
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
304+
)
305+
FROM Salaries;
306+
307+
308+
-- same like ORDER BY
309+
SELECT emp_no,
310+
salary,
311+
COUNT(salary) OVER(
312+
PARTITION BY emp_no
313+
ORDER BY salary
314+
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
315+
)
316+
FROM Salaries;
317+
318+
/*------------------------------------------------------------------------------------------------------------*/
319+
320+
321+
322+
323+
324+
325+
326+
201 KB
Loading

0 commit comments

Comments
 (0)