Skip to content

Commit 5fc7e99

Browse files
committed
WIP SQL window functions
1 parent cca6347 commit 5fc7e99

File tree

2 files changed

+350
-0
lines changed

2 files changed

+350
-0
lines changed
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
---
2+
title: SQL window functions
3+
list_title: Window functions
4+
description: >
5+
....
6+
menu:
7+
influxdb3_cloud_dedicated:
8+
name: Window
9+
parent: sql-functions
10+
weight: 309
11+
related:
12+
- /influxdb3/cloud-dedicated/query-data/sql/aggregate-select/
13+
14+
# source: /content/shared/sql-reference/functions/aggregate.md
15+
---
16+
17+
A _window function_ performs an operation across a set of rows related to the
18+
current row. This is similar to the type of operations
19+
[aggregate functions](/influxdb3/cloud-dedicated/reference/sql/functions/aggregate/)
20+
perform. However, window functions do not return a single output row per group
21+
like non-window aggregate functions do. Instead, rows retain their separate
22+
identities.
23+
24+
For example, the following query uses the {{< influxdb3/home-sample-link >}}
25+
and returns each temperature reading with the average temperature per room over
26+
the queried time range:
27+
28+
```sql
29+
SELECT
30+
time,
31+
room,
32+
temp,
33+
avg(temp) OVER (PARTITION BY room) AS avg_room_temp
34+
FROM
35+
home
36+
WHERE
37+
time >= '2022-01-01T08:00:00Z'
38+
AND time <= '2022-01-01T12:00:00Z'
39+
ORDER BY
40+
room,
41+
time
42+
```
43+
44+
| time | room | temp | avg_room_temp |
45+
| :------------------ | :---------- | ---: | ------------: |
46+
| 2022-01-01T08:00:00 | Kitchen | 21.0 | 22.32 |
47+
| 2022-01-01T09:00:00 | Kitchen | 23.0 | 22.32 |
48+
| 2022-01-01T10:00:00 | Kitchen | 22.7 | 22.32 |
49+
| 2022-01-01T11:00:00 | Kitchen | 22.4 | 22.32 |
50+
| 2022-01-01T12:00:00 | Kitchen | 22.5 | 22.32 |
51+
| 2022-01-01T08:00:00 | Living Room | 21.1 | 21.74 |
52+
| 2022-01-01T09:00:00 | Living Room | 21.4 | 21.74 |
53+
| 2022-01-01T10:00:00 | Living Room | 21.8 | 21.74 |
54+
| 2022-01-01T11:00:00 | Living Room | 22.2 | 21.74 |
55+
| 2022-01-01T12:00:00 | Living Room | 22.2 | 21.74 |
56+
57+
## Window function syntax
58+
59+
```sql
60+
function([expr])
61+
OVER(
62+
[PARTITION BY expr[, …]]
63+
[ORDER BY expr [ ASC | DESC ][, …]]
64+
[ frame_clause ]
65+
)
66+
```
67+
68+
### OVER clause
69+
70+
Window functions use an `OVER` clause directly following the window function's
71+
name and arguments. The `OVER` clause syntactically distinguishes a window
72+
function from a normal function or non-window aggregate function and determines
73+
how rows are split up for the window operation.
74+
75+
### PARTITION BY clause
76+
77+
The `PARTITION BY` clause in the `OVER` clause divides the rows into groups, or
78+
partitions, that share the same values of the `PARTITION BY` expressions.
79+
The window function operates on all the rows in the same partition as the
80+
current row.
81+
82+
### ORDER BY clause
83+
84+
The `ORDER BY` clause inside of the `OVER` clause controls the order that the
85+
window function processors rows in each partition.
86+
87+
> [!Note]
88+
> The `ORDER BY` clause in an `OVER` clause is separate from the `ORDER BY`
89+
> clause of the query and only determines the order that rows in each partition
90+
> are processed in.
91+
92+
### Frame clause
93+
94+
The frame clause can be one of the following:
95+
96+
```sql
97+
{ RANGE | ROWS | GROUPS } frame_start
98+
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end
99+
```
100+
101+
and **frame_start** and **frame_end** can be one of
102+
103+
```sql
104+
UNBOUNDED PRECEDING
105+
offset PRECEDING
106+
CURRENT ROW
107+
offset FOLLOWING
108+
UNBOUNDED FOLLOWING
109+
```
110+
111+
where **offset** is an non-negative integer.
112+
113+
`RANGE` and `GROUPS` modes require an `ORDER BY` clause (with `RANGE` the `ORDER BY` must
114+
specify exactly one column).
115+
116+
#### Framing modes
117+
118+
##### RANGE
119+
120+
##### ROWS
121+
122+
##### GROUPs
123+
124+
125+
126+
```sql
127+
SELECT depname, empno, salary,
128+
rank() OVER (PARTITION BY depname ORDER BY salary DESC)
129+
FROM empsalary;
130+
131+
+-----------+-------+--------+--------+
132+
| depname | empno | salary | rank |
133+
+-----------+-------+--------+--------+
134+
| personnel | 2 | 3900 | 1 |
135+
| develop | 8 | 6000 | 1 |
136+
| develop | 10 | 5200 | 2 |
137+
| develop | 11 | 5200 | 2 |
138+
| develop | 9 | 4500 | 4 |
139+
| develop | 7 | 4200 | 5 |
140+
| sales | 1 | 5000 | 1 |
141+
| sales | 4 | 4800 | 2 |
142+
| personnel | 5 | 3500 | 2 |
143+
| sales | 3 | 4800 | 2 |
144+
+-----------+-------+--------+--------+
145+
```
146+
147+
There is another important concept associated with window functions: for each
148+
row, there is a set of rows within its partition called its window frame. Some
149+
window functions act only on the rows of the window frame, rather than of the
150+
whole partition. Here is an example of using window frames in queries:
151+
152+
```sql
153+
SELECT depname, empno, salary,
154+
avg(salary) OVER(ORDER BY salary ASC ROWS BETWEEN 1 PRECEDING AND 1
155+
FOLLOWING) AS avg,
156+
min(salary) OVER(ORDER BY empno ASC ROWS BETWEEN UNBOUNDED PRECEDING AND
157+
CURRENT ROW) AS cum_min
158+
FROM empsalary
159+
ORDER BY empno ASC;
160+
161+
+-----------+-------+--------+--------------------+---------+
162+
| depname | empno | salary | avg | cum_min |
163+
+-----------+-------+--------+--------------------+---------+
164+
| sales | 1 | 5000 | 5000.0 | 5000 |
165+
| personnel | 2 | 3900 | 3866.6666666666665 | 3900 |
166+
| sales | 3 | 4800 | 4700.0 | 3900 |
167+
| sales | 4 | 4800 | 4866.666666666667 | 3900 |
168+
| personnel | 5 | 3500 | 3700.0 | 3500 |
169+
| develop | 7 | 4200 | 4200.0 | 3500 |
170+
| develop | 8 | 6000 | 5600.0 | 3500 |
171+
| develop | 9 | 4500 | 4500.0 | 3500 |
172+
| develop | 10 | 5200 | 5133.333333333333 | 3500 |
173+
| develop | 11 | 5200 | 5466.666666666667 | 3500 |
174+
+-----------+-------+--------+--------------------+---------+
175+
```
176+
177+
When a query involves multiple window functions, it is possible to write out
178+
each one with a separate OVER clause, but this is duplicative and error-prone if
179+
the same windowing behavior is wanted for several functions. Instead, each
180+
windowing behavior can be named in a WINDOW clause and then referenced in OVER.
181+
For example:
182+
183+
```sql
184+
SELECT sum(salary) OVER w, avg(salary) OVER w
185+
FROM empsalary
186+
WINDOW w AS (PARTITION BY depname ORDER BY salary DESC);
187+
```
188+
189+
## Aggregate functions
190+
191+
All [aggregate functions](/influxdb3/cloud-dedicated/reference/sql/functions/aggregate/)
192+
can be used as window functions.
193+
194+
## Ranking Functions
195+
196+
- [cume_dist](#cume_dist)
197+
- [dense_rank](#dense_rank)
198+
- [ntile](#ntile)
199+
- [percent_rank](#percent_rank)
200+
- [rank](#rank)
201+
- [row_number](#row_number)
202+
203+
### `cume_dist`
204+
205+
Relative rank of the current row: (number of rows preceding or peer with current
206+
row) / (total rows).
207+
208+
```sql
209+
cume_dist()
210+
```
211+
212+
### `dense_rank`
213+
214+
Returns the rank of the current row without gaps. This function ranks rows in a
215+
dense manner, meaning consecutive ranks are assigned even for identical values.
216+
217+
```sql
218+
dense_rank()
219+
```
220+
221+
### `ntile`
222+
223+
Integer ranging from 1 to the argument value, dividing the partition as equally
224+
as possible.
225+
226+
```sql
227+
ntile(expression)
228+
```
229+
230+
#### Arguments
231+
232+
- **expression**: An integer describing the number groups the partition should
233+
be split into.
234+
235+
### `percent_rank`
236+
237+
Returns the percentage rank of the current row within its partition. The value
238+
ranges from 0 to 1 and is computed as `(rank - 1) / (total_rows - 1)`.
239+
240+
```sql
241+
percent_rank()
242+
```
243+
244+
### `rank`
245+
246+
Returns the rank of the current row within its partition, allowing gaps between
247+
ranks. This function provides a ranking similar to `row_number`, but skips ranks
248+
for identical values.
249+
250+
```sql
251+
rank()
252+
```
253+
254+
### `row_number`
255+
256+
Number of the current row within its partition, counting from 1.
257+
258+
```sql
259+
row_number()
260+
```
261+
262+
## Analytical Functions
263+
264+
- [first_value](#first_value)
265+
- [lag](#lag)
266+
- [last_value](#last_value)
267+
- [lead](#lead)
268+
- [nth_value](#nth_value)
269+
270+
### `first_value`
271+
272+
Returns value evaluated at the row that is the first row of the window frame.
273+
274+
```sql
275+
first_value(expression)
276+
```
277+
278+
#### Arguments
279+
280+
- **expression**: Expression to operate on.
281+
282+
### `lag`
283+
284+
Returns value evaluated at the row that is offset rows before the current row
285+
within the partition; if there is no such row, instead return default (which
286+
must be of the same type as value).
287+
288+
```sql
289+
lag(expression, offset, default)
290+
```
291+
292+
#### Arguments
293+
294+
- **expression**: Expression to operate on.
295+
- **offset**: Integer. Specifies how many rows back the value of expression
296+
should be retrieved. Defaults to 1.
297+
- **default**: The default value if the offset is not within the partition. Must
298+
be of the same type as expression.
299+
300+
### `last_value`
301+
302+
Returns value evaluated at the row that is the last row of the window frame.
303+
304+
```sql
305+
last_value(expression)
306+
```
307+
308+
#### Arguments
309+
310+
- **expression**: Expression to operate on.
311+
312+
### `lead`
313+
314+
Returns value evaluated at the row that is offset rows after the current row
315+
within the partition; if there is no such row, instead return default (which
316+
must be of the same type as value).
317+
318+
```sql
319+
lead(expression, offset, default)
320+
```
321+
322+
#### Arguments
323+
324+
- **expression**: Expression to operate on.
325+
- **offset**: Integer. Specifies how many rows forward the value of expression
326+
should be retrieved. Defaults to 1.
327+
- **default**: The default value if the offset is not within the partition. Must
328+
be of the same type as expression.
329+
330+
### `nth_value`
331+
332+
Returns value evaluated at the row that is the nth row of the window frame
333+
(counting from 1); null if no such row.
334+
335+
```sql
336+
nth_value(expression, n)
337+
```
338+
339+
#### Arguments
340+
341+
- **expression**: The name the column of which nth value to retrieve.
342+
- **n**: Integer. Specifies the n in nth.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{{- $productPathData := split .Page.RelPermalink "/" -}}
2+
{{- $product := index $productPathData 2 -}}
3+
{{- $isDistributed := in (slice "cloud-dedicated" "cloud-serverless" "clustered") $product -}}
4+
{{- if $isDistributed -}}
5+
<a href="/influxdb3/{{ $product }}//reference/sample-data/#get-started-home-sensor-data">Get started home sensor sample data</a>
6+
{{- else -}}
7+
<a href="/influxdb3/{{ $product }}//reference/sample-data/#home-sensor-data">Home sensor sample data</a>
8+
{{- end -}}

0 commit comments

Comments
 (0)