Repository navigation
Expand file tree
/
Copy path19_SQL_Window-functions-basics.sql
More file actions
178 lines (139 loc) · 4.46 KB
/
Copy path19_SQL_Window-functions-basics.sql
File metadata and controls
178 lines (139 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
-----------------WINDOW FUNCTIONS----------------
/*
Pozwala przeprowadzac kalkulacji (np. aggregacje) na specyficznym
podzbiorze danych, bez tracenia poziomu detali wierszy.
Window Functions robia tkzw. ROW-LEVEL Calculations (wierszy bedzie tyle samo co bylo
wczesniej).
WINDOW FUNCTIONS syntax:
Window Function f(x) OVER Clause
Over Clause dzieli sie na:
- Partition clause,
- Order Clause,
- Frame Clause
OVER CLAUSE mowi SQL ze uzyta funkcja to funkcja okna,
definiuje tez okno lub podzbior danych.
ex.
AVG(Sales) OVER (PARTITION BY Category ORDER BY OrderDate ROWS UNBOUNDED PRECEDING)
ZASADY WINDOW FUNCTIONS:
- funkcji okna mozna uzywac tylko w selekcie lub w order by
- nesting funkcji okna nie jest dozwolony (nie mozna dac funkcji okna do funkcji okna)
- SQL wykonuje funkcje okna po klauzuli WHERE
- funkcja onka moze byc uzyta z GROUP BY w tym samym zapytaniu, TYLKO jesli takie same
kolumny sa w uzyciu
*/
USE SalesDB
/*task: Find the total Sales Across all orders*/
SELECT
SUM(Sales) as SumOfSales
FROM Sales.Orders;
/*task: Find the total sales for each product*/
SELECT
ProductID,
SUM(Sales) as SumOfSales
FROM Sales.Orders
GROUP BY ProductID; -- result dimension okresla granularity
/*task: Find the total sales for each product, additionally provide
details such as order id & order date*/
SELECT
ProductID,
OrderID,
OrderDate,
SUM(Sales) OVER(PARTITION BY ProductID) as SumOfSales -- PARTITION BY to takie GROUP BY tylko w funkcji
--okna
FROM Sales.Orders
-------------PARTITION BY------------
/*
Dzieli result set na partycje (okna).
Partition by dzieli wiersze na grupy, bazujac na kolumnach.
*/
/*task1: Find the total sales across all orders additionally provide
details such as order & order date*/
SELECT
OrderID,
OrderDate,
SUM(Sales) OVER() as SumOfSales
FROM Sales.Orders;
/*task2: Find the total sales for each product, additionally provide
details such as order id & order date*/
SELECT
ProductID,
OrderID,
OrderDate,
SUM(Sales) OVER(PARTITION BY ProductID) as [task 2],
SUM(Sales) OVER() as SumOfSales -- przyklad ze mozemy inne okna robic w tym samym selekcie
FROM Sales.Orders;
/*task3: Find the total sales for each combination of product and order status*/
SELECT
ProductID,
OrderID,
OrderDate,
OrderStatus,
SUM(Sales) OVER(PARTITION BY ProductID,OrderStatus) as [task3]
FROM Sales.Orders;
---------------ORDER BY---------------
/*
Sortuje dane w oknie (ASC lub DESC)
*/
/*task: Rank each order based on their sales from highest to lowest,
additionally provide details such as order id & order date */
SELECT
RANK() OVER(ORDER BY Sales DESC) as [ranking zamowien],
Sales,
OrderID,
OrderDate
FROM Sales.Orders;
----------------FRAME----------------
/*
Definiuje podzbior wieszy w kazdym oknie, ktore sa istotne
dla obliczen.Robimy takie okno w oknie, bedzie sie ono przesuwac!
Ten frame robi obliczenia do logiki window function.
Jesli zapomnisz jak to dziala to lepiej zobaczyc u barry wizualizacje.
Frame Types:
-ROWS,
-RANGE
Frame Lower Value Boundary:
-CURRENT ROW,
-N PRECIDING,
-UNBOUNDED PRECIDING,
Frame Higher Value Boundary:
-CURRENT ROW
-N FOLLOWING
-UNBOUNDED FOLLOWING
ZASADY:
-frame moze byc tylko uzyty z klauzula ORDER BY
-Lower Value musi byc przed Higher Value (boundary)
*/
SELECT
OrderID,
OrderDate,
OrderStatus,
Sales,
SUM(Sales) OVER(PARTITION BY OrderStatus ORDER BY OrderDate
ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING) as TotalSales
FROM Sales.Orders;
--NOTE: Frame jest kalkulowany w obrebie danego okna! nie wszystkich wierszow tabeli.
--NOTE: ORDER BY ma default frame: RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
--NOTE: Istnieje forma skrocona dla preciding i current row mianowicie:
/*
normal: ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING
shortened: ROWS 2 FOLLOWING
*/
/*task: Find the total sales for each order status, only for two products
101 and 102 */
SELECT
ProductID,
SUM(Sales) OVER(PARTITION BY ProductID) as TotalSales
FROM Sales.Orders
WHERE ProductID IN (101,102)
/*task: Rank Customers based on their total sales*/
SELECT
CustomerID,
SUM(Sales) TotalSales,
RANK() OVER(ORDER BY SUM(Sales) DESC) as [ranking]
FROM Sales.Orders
GROUP BY CustomerID;
--NOTE: Barra slusznie zauwazyl ze sa to 2 rozne kalkulacje, rank musi byc
-- funkcja okna natomiast total sales mozna zgrupowac przez GROUP BY.
-- podobno dobra praktyka jest gropowanie prostych rzeczy przez wlasnie GROUP BY.
-- te zadanie to przykad zasady 4.
-- najpierw robimy group by potem window functions w takich przykladach