1
+ /* ********* Filterig, Join and Aggregration ************/
2
+
3
+ /* we want to know person's salary comparing to his/her department average salary */
4
+ SELECT
5
+ s .last_name ,s .salary ,s .department ,
6
+ (SELECT ROUND(AVG (salary),2 )
7
+ FROM staff s2
8
+ WHERE s2 .department = s .department ) AS department_average_salary
9
+ FROM staff s;
10
+
11
+
12
+ /* how many people are earning above/below the average salary of his/her department ? */
13
+ CREATE VIEW vw_salary_comparision_by_department
14
+ AS
15
+ SELECT
16
+ s .department ,
17
+ (
18
+ s .salary > (SELECT ROUND(AVG (s2 .salary ),2 )
19
+ FROM staff s2
20
+ WHERE s2 .department = s .department )
21
+ )AS is_higher_than_dept_avg_salary
22
+ FROM staff s
23
+ ORDER BY s .department ;
24
+
25
+
26
+ SELECT * FROM vw_salary_comparision_by_department;
27
+
28
+ SELECT department, is_higher_than_dept_avg_salary, COUNT (* ) AS total_employees
29
+ FROM vw_salary_comparision_by_department
30
+ GROUP BY 1 ,2 ;
31
+
32
+
33
+ -- --------------------------------------------------------------------------------------------
34
+
35
+ /* Assume that people who earn at latest 100,000 salary is Executive.
36
+ We want to know the average salary for executives for each department.
37
+
38
+ Data Interpretation: it seem like Sports department has the highest average salary for Executives
39
+ where Movie department has the lowest.*/
40
+ SELECT department, ROUND(AVG (salary),2 ) AS average_salary
41
+ FROM staff
42
+ WHERE salary >= 100000
43
+ GROUP BY department
44
+ ORDER BY 2 DESC ;
45
+
46
+
47
+ /* who earn the most in the company?
48
+ It seems like Stanley Grocery earns the most.
49
+ */
50
+ SELECT last_name, department, salary
51
+ FROM staff
52
+ WHERE salary = (
53
+ SELECT MAX (s2 .salary )
54
+ FROM staff s2
55
+ );
56
+
57
+
58
+
59
+ /* who earn the most in his/her own department */
60
+ SELECT s .department , s .last_name , s .salary
61
+ FROM staff s
62
+ WHERE s .salary = (
63
+ SELECT MAX (s2 .salary )
64
+ FROM staff s2
65
+ WHERE s2 .department = s .department
66
+ )
67
+ ORDER BY 1 ;
68
+
69
+ -- --------------------------------------------------------------------------------------------
70
+
71
+ SELECT * FROM company_divisions;
72
+
73
+ /* full details info of employees with company division
74
+ Based on the results, we see that there are only 953 rows returns. We know that there are 1000 staffs.
75
+ */
76
+ SELECT s .last_name , s .department , cd .company_division
77
+ FROM staff s
78
+ JOIN company_divisions cd
79
+ ON cd .department = s .department ;
80
+
81
+
82
+ /* now all 1000 staffs are returned, but some 47 people have missing company - division.*/
83
+ SELECT s .last_name , s .department , cd .company_division
84
+ FROM staff s
85
+ LEFT JOIN company_divisions cd
86
+ ON cd .department = s .department ;
87
+
88
+
89
+ /* who are those people with missing company division?
90
+ Data Interpretation: it seems like all staffs from "books" department have missing company division.
91
+ We may want to inform our IT team to add Books department in corresponding company division.
92
+ */
93
+ SELECT s .last_name , s .department , cd .company_division
94
+ FROM staff s
95
+ LEFT JOIN company_divisions cd
96
+ ON cd .department = s .department
97
+ WHERE company_division IS NULL ;
98
+
99
+
100
+ -- --------------------------------------------------------------------------------------------
101
+
102
+ CREATE VIEW vw_staff_div_reg AS
103
+ SELECT s.* , cd .company_division , cr .company_regions
104
+ FROM staff s
105
+ LEFT JOIN company_divisions cd ON s .department = cd .department
106
+ LEFT JOIN company_regions cr ON s .region_id = cr .region_id ;
107
+
108
+
109
+ SELECT COUNT (* )
110
+ FROM vw_staff_div_reg;
111
+
112
+
113
+ /* How many staffs are in each company regions */
114
+ SELECT company_regions, COUNT (* ) AS total_employees
115
+ FROM vw_staff_div_reg
116
+ GROUP BY 1
117
+ ORDER BY 1 ;
118
+
119
+
120
+ SELECT company_regions, company_division, COUNT (* ) AS total_employees
121
+ FROM vw_staff_div_reg
122
+ GROUP BY 1 ,2
123
+ ORDER BY 1 ,2 ;
124
+
125
+
126
+ /* **** Grouping Sets *****************/
127
+ -- Grouping Sets : allows to have more than one grouping in the results table
128
+ -- there is no need to seperately use group by per query statement
129
+
130
+ -- 2 groupings
131
+ SELECT company_regions, company_division, COUNT (* ) AS total_employees
132
+ FROM vw_staff_div_reg
133
+ GROUP BY
134
+ GROUPING SETS(company_regions, company_division)
135
+ ORDER BY 1 ,2 ;
136
+
137
+
138
+ -- 3 groupings
139
+ SELECT company_regions, company_division, gender, COUNT (* ) AS total_employees
140
+ FROM vw_staff_div_reg
141
+ GROUP BY
142
+ GROUPING SETS(company_regions, company_division, gender)
143
+ ORDER BY 1 , 2
144
+
145
+ -- --------------------------------------------------------------------------------------------
146
+
147
+
148
+ CREATE OR REPLACE VIEW vw_staff_div_reg_country AS
149
+ SELECT s.* , cd .company_division , cr .company_regions , cr .country
150
+ FROM staff s
151
+ LEFT JOIN company_divisions cd ON s .department = cd .department
152
+ LEFT JOIN company_regions cr ON s .region_id = cr .region_id ;
153
+
154
+ /* employees per regions and country */
155
+ SELECT company_regions, country, COUNT (* ) AS total_employees
156
+ FROM vw_staff_div_reg_country
157
+ GROUP BY
158
+ company_regions, country
159
+ ORDER BY country, company_regions;
160
+
161
+ -- ------------ ROLL UP & CUBE to create Sub Totals ----------------------------------------
162
+ -- both are sub clauses of Group by
163
+
164
+
165
+ -- ------------ ROLL UP ----------------
166
+ -- is used to generate sub totals and grand totals
167
+
168
+ /* number of employees per regions & country, Then sub totals per Country, Then toal for whole table*/
169
+ SELECT country,company_regions, COUNT (* ) AS total_employees
170
+ FROM vw_staff_div_reg_country
171
+ GROUP BY
172
+ ROLLUP(country, company_regions)
173
+ ORDER BY country, company_regions;
174
+
175
+
176
+ -- --------- CUBE -------------------
177
+ SELECT company_division, company_regions, COUNT (* ) AS total_employees
178
+ FROM vw_staff_div_reg_country
179
+ GROUP BY
180
+ CUBE(company_division, company_regions)
181
+ ORDER BY company_division, company_regions;
182
+
183
+
184
+ -- -----------------------------------------------------------------------------
185
+
186
+ /* Difference between Roll Up and Cube
187
+
188
+ Reference: https://www.postgresqltutorial.com/postgresql-rollup/
189
+
190
+ For example, the CUBE (c1,c2,c3) makes all eight possible grouping sets:
191
+ (c1, c2, c3)
192
+ (c1, c2)
193
+ (c2, c3)
194
+ (c1,c3)
195
+ (c1)
196
+ (c2)
197
+ (c3)
198
+ ()
199
+
200
+
201
+ However, the ROLLUP(c1,c2,c3) generates only four grouping sets, assuming the hierarchy c1 > c2 > c3 as follows:
202
+
203
+ (c1, c2, c3)
204
+ (c1, c2)
205
+ (c1)
206
+ ()
207
+
208
+ */
209
+
210
+ SELECT company_division, company_regions, country, COUNT (* ) AS total_employees
211
+ FROM vw_staff_div_reg_country
212
+ GROUP BY
213
+ ROLLUP(company_division, company_regions, country)
214
+ ORDER BY company_division, company_regions, country;
215
+
216
+
217
+ SELECT company_division, company_regions, country, COUNT (* ) AS total_employees
218
+ FROM vw_staff_div_reg_country
219
+ GROUP BY
220
+ CUBE(company_division, company_regions, country)
221
+ ORDER BY company_division, company_regions, country;
222
+
223
+
224
+ -- -----------------------------------------------------------------------------
225
+
226
+ -- ---------- FETCH FIRST ----------
227
+ /*
228
+ Fetch First works different from Limit.
229
+
230
+ For Fetch First, Order By Clause works first for sorting. Then Fetch First selets the rows.
231
+
232
+ For Limit, Limit acutally limits the rows and then performs the operations.
233
+
234
+ */
235
+
236
+
237
+ /* What are the top salary earners ? */
238
+ SELECT last_name, salary
239
+ FROM staff
240
+ ORDER BY salary DESC
241
+ FETCH FIRST 10 ROWS ONLY;
242
+
243
+
244
+ /* Top 5 division with highest number of employees*/
245
+ SELECT
246
+ company_division,
247
+ COUNT (* ) AS total_employees
248
+ FROM vw_staff_div_reg_country
249
+ GROUP BY company_division
250
+ ORDER BY company_division
251
+ FETCH FIRST 5 ROWS ONLY;
252
+
253
+
254
+
255
+ SELECT
256
+ company_division,
257
+ COUNT (* ) AS total_employees
258
+ FROM vw_staff_div_reg_country
259
+ GROUP BY company_division
260
+ ORDER BY company_division
261
+ LIMIT 5 ;
262
+
0 commit comments