Skip to content

Commit 1fca0be

Browse files
authored
docs: refresh window value function examples (databendlabs#2856)
1 parent 222f7d7 commit 1fca0be

File tree

3 files changed

+267
-119
lines changed

3 files changed

+267
-119
lines changed

docs/en/sql-reference/20-sql-functions/08-window-functions/first-value.md

Lines changed: 105 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ See also:
1616
## Syntax
1717

1818
```sql
19-
FIRST_VALUE(expression)
19+
FIRST_VALUE(expression) [ { RESPECT | IGNORE } NULLS ]
2020
OVER (
2121
[ PARTITION BY partition_expression ]
2222
ORDER BY sort_expression [ ASC | DESC ]
@@ -25,50 +25,123 @@ OVER (
2525
```
2626

2727
**Arguments:**
28-
- `expression`: Required. The column or expression to return the first value from
29-
- `PARTITION BY`: Optional. Divides rows into partitions
30-
- `ORDER BY`: Required. Determines the ordering within the window
31-
- `window_frame`: Optional. Defines the window frame (default: RANGE UNBOUNDED PRECEDING)
28+
- `expression`: Required. The column or expression to return the first value from.
29+
- `PARTITION BY`: Optional. Divides rows into partitions.
30+
- `ORDER BY`: Required. Determines the ordering within the window.
31+
- `window_frame`: Optional. Defines the window frame. The default is `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`.
3232

3333
**Notes:**
34-
- Returns the first value in the ordered window frame
35-
- Supports `IGNORE NULLS` and `RESPECT NULLS` options
36-
- Useful for finding the earliest/lowest value in each group
34+
- Returns the first value in the ordered window frame.
35+
- Supports `IGNORE NULLS` to skip null values and `RESPECT NULLS` to keep the default behaviour.
36+
- Specify an explicit window frame (for example, `ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`) when you need row-based semantics instead of the default range frame.
37+
- Useful for finding the earliest or lowest value in each group or time window.
3738

3839
## Examples
3940

4041
```sql
41-
-- Create sample data
42-
CREATE TABLE scores (
43-
student VARCHAR(20),
44-
score INT
42+
-- Sample order data
43+
CREATE OR REPLACE TABLE orders_window_demo (
44+
customer VARCHAR,
45+
order_id INT,
46+
order_time TIMESTAMP,
47+
amount INT,
48+
sales_rep VARCHAR
4549
);
4650

47-
INSERT INTO scores VALUES
48-
('Alice', 95),
49-
('Bob', 87),
50-
('Charlie', 82),
51-
('David', 78),
52-
('Eve', 92);
51+
INSERT INTO orders_window_demo VALUES
52+
('Alice', 1001, to_timestamp('2024-05-01 09:00:00'), 120, 'Erin'),
53+
('Alice', 1002, to_timestamp('2024-05-01 11:00:00'), 135, NULL),
54+
('Alice', 1003, to_timestamp('2024-05-02 14:30:00'), 125, 'Glen'),
55+
('Bob', 1004, to_timestamp('2024-05-01 08:30:00'), 90, NULL),
56+
('Bob', 1005, to_timestamp('2024-05-01 20:15:00'), 105, 'Kai'),
57+
('Bob', 1006, to_timestamp('2024-05-03 10:00:00'), 95, NULL),
58+
('Carol', 1007, to_timestamp('2024-05-04 09:45:00'), 80, 'Lily');
5359
```
5460

55-
**Get the highest score (first value when ordered by score DESC):**
61+
**Example 1. First purchase per customer**
5662

5763
```sql
58-
SELECT student, score,
59-
FIRST_VALUE(score) OVER (ORDER BY score DESC) AS highest_score,
60-
FIRST_VALUE(student) OVER (ORDER BY score DESC) AS top_student
61-
FROM scores
62-
ORDER BY score DESC;
64+
SELECT customer,
65+
order_id,
66+
order_time,
67+
amount,
68+
FIRST_VALUE(amount) OVER (
69+
PARTITION BY customer
70+
ORDER BY order_time
71+
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
72+
) AS first_order_amount
73+
FROM orders_window_demo
74+
ORDER BY customer, order_time;
6375
```
6476

6577
Result:
6678
```
67-
student | score | highest_score | top_student
68-
--------+-------+---------------+------------
69-
Alice | 95 | 95 | Alice
70-
Eve | 92 | 95 | Alice
71-
Bob | 87 | 95 | Alice
72-
Charlie | 82 | 95 | Alice
73-
David | 78 | 95 | Alice
74-
```
79+
customer | order_id | order_time | amount | first_order_amount
80+
---------+----------+----------------------+--------+--------------------
81+
Alice | 1001 | 2024-05-01 09:00:00 | 120 | 120
82+
Alice | 1002 | 2024-05-01 11:00:00 | 135 | 120
83+
Alice | 1003 | 2024-05-02 14:30:00 | 125 | 120
84+
Bob | 1004 | 2024-05-01 08:30:00 | 90 | 90
85+
Bob | 1005 | 2024-05-01 20:15:00 | 105 | 90
86+
Bob | 1006 | 2024-05-03 10:00:00 | 95 | 90
87+
Carol | 1007 | 2024-05-04 09:45:00 | 80 | 80
88+
```
89+
90+
**Example 2. First order in the trailing 24 hours**
91+
92+
```sql
93+
SELECT customer,
94+
order_id,
95+
order_time,
96+
FIRST_VALUE(order_id) OVER (
97+
PARTITION BY customer
98+
ORDER BY order_time
99+
RANGE BETWEEN INTERVAL 1 DAY PRECEDING AND CURRENT ROW
100+
) AS first_order_in_24h
101+
FROM orders_window_demo
102+
ORDER BY customer, order_time;
103+
```
104+
105+
Result:
106+
```
107+
customer | order_id | order_time | first_order_in_24h
108+
---------+----------+----------------------+--------------------
109+
Alice | 1001 | 2024-05-01 09:00:00 | 1001
110+
Alice | 1002 | 2024-05-01 11:00:00 | 1001
111+
Alice | 1003 | 2024-05-02 14:30:00 | 1003
112+
Bob | 1004 | 2024-05-01 08:30:00 | 1004
113+
Bob | 1005 | 2024-05-01 20:15:00 | 1004
114+
Bob | 1006 | 2024-05-03 10:00:00 | 1006
115+
Carol | 1007 | 2024-05-04 09:45:00 | 1007
116+
```
117+
118+
**Example 3. Skip nulls to find the first named sales rep**
119+
120+
```sql
121+
SELECT customer,
122+
order_id,
123+
sales_rep,
124+
FIRST_VALUE(sales_rep) RESPECT NULLS OVER (
125+
PARTITION BY customer
126+
ORDER BY order_time
127+
) AS first_rep_respect,
128+
FIRST_VALUE(sales_rep) IGNORE NULLS OVER (
129+
PARTITION BY customer
130+
ORDER BY order_time
131+
) AS first_rep_ignore
132+
FROM orders_window_demo
133+
ORDER BY customer, order_id;
134+
```
135+
136+
Result:
137+
```
138+
customer | order_id | sales_rep | first_rep_respect | first_rep_ignore
139+
---------+----------+-----------+-------------------+------------------
140+
Alice | 1001 | Erin | Erin | Erin
141+
Alice | 1002 | NULL | Erin | Erin
142+
Alice | 1003 | Glen | Erin | Erin
143+
Bob | 1004 | NULL | NULL | NULL
144+
Bob | 1005 | Kai | NULL | Kai
145+
Bob | 1006 | NULL | NULL | Kai
146+
Carol | 1007 | Lily | Lily | Lily
147+
```

docs/en/sql-reference/20-sql-functions/08-window-functions/last-value.md

Lines changed: 107 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ See also:
1616
## Syntax
1717

1818
```sql
19-
LAST_VALUE(expression)
19+
LAST_VALUE(expression) [ { RESPECT | IGNORE } NULLS ]
2020
OVER (
2121
[ PARTITION BY partition_expression ]
2222
ORDER BY sort_expression [ ASC | DESC ]
@@ -25,57 +25,125 @@ OVER (
2525
```
2626

2727
**Arguments:**
28-
- `expression`: Required. The column or expression to return the last value from
29-
- `PARTITION BY`: Optional. Divides rows into partitions
30-
- `ORDER BY`: Required. Determines the ordering within the window
31-
- `window_frame`: Optional. Defines the window frame (default: RANGE UNBOUNDED PRECEDING)
28+
- `expression`: Required. The column or expression to return the last value from.
29+
- `PARTITION BY`: Optional. Divides rows into partitions.
30+
- `ORDER BY`: Required. Determines the ordering within the window.
31+
- `window_frame`: Optional. Defines the window frame. The default is `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`.
3232

3333
**Notes:**
34-
- Returns the last value in the ordered window frame
35-
- Supports `IGNORE NULLS` and `RESPECT NULLS` options
36-
- Often requires explicit window frame to get expected results
37-
- Useful for finding the latest/highest value in each group
34+
- Returns the last value in the ordered window frame.
35+
- Supports `IGNORE NULLS` to skip null values and `RESPECT NULLS` to keep the default behaviour.
36+
- Use a frame that ends after the current row (for example, `ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING`) when you need the true last row of a partition.
37+
- Useful for finding the latest value in each group, or the most recent value inside a look-ahead window.
3838

3939
## Examples
4040

4141
```sql
42-
-- Create sample data
43-
CREATE TABLE scores (
44-
student VARCHAR(20),
45-
score INT
42+
-- Sample order data
43+
CREATE OR REPLACE TABLE orders_window_demo (
44+
customer VARCHAR,
45+
order_id INT,
46+
order_time TIMESTAMP,
47+
amount INT,
48+
sales_rep VARCHAR
4649
);
4750

48-
INSERT INTO scores VALUES
49-
('Alice', 95),
50-
('Bob', 87),
51-
('Charlie', 82),
52-
('David', 78),
53-
('Eve', 92);
51+
INSERT INTO orders_window_demo VALUES
52+
('Alice', 1001, to_timestamp('2024-05-01 09:00:00'), 120, 'Erin'),
53+
('Alice', 1002, to_timestamp('2024-05-01 11:00:00'), 135, NULL),
54+
('Alice', 1003, to_timestamp('2024-05-02 14:30:00'), 125, 'Glen'),
55+
('Bob', 1004, to_timestamp('2024-05-01 08:30:00'), 90, NULL),
56+
('Bob', 1005, to_timestamp('2024-05-01 20:15:00'), 105, 'Kai'),
57+
('Bob', 1006, to_timestamp('2024-05-03 10:00:00'), 95, NULL),
58+
('Carol', 1007, to_timestamp('2024-05-04 09:45:00'), 80, 'Lily');
5459
```
5560

56-
**Get the lowest score (last value when ordered by score DESC):**
61+
**Example 1. Latest order in each customer partition**
5762

5863
```sql
59-
SELECT student, score,
60-
LAST_VALUE(score) OVER (
61-
ORDER BY score DESC
62-
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
63-
) AS lowest_score,
64-
LAST_VALUE(student) OVER (
65-
ORDER BY score DESC
66-
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
67-
) AS lowest_student
68-
FROM scores
69-
ORDER BY score DESC;
64+
SELECT customer,
65+
order_id,
66+
order_time,
67+
LAST_VALUE(order_id) OVER (
68+
PARTITION BY customer
69+
ORDER BY order_time
70+
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
71+
) AS last_order_for_customer
72+
FROM orders_window_demo
73+
ORDER BY customer, order_time;
7074
```
7175

7276
Result:
7377
```
74-
student | score | lowest_score | lowest_student
75-
--------+-------+--------------+---------------
76-
Alice | 95 | 78 | David
77-
Eve | 92 | 78 | David
78-
Bob | 87 | 78 | David
79-
Charlie | 82 | 78 | David
80-
David | 78 | 78 | David
81-
```
78+
customer | order_id | order_time | last_order_for_customer
79+
---------+----------+----------------------+-------------------------
80+
Alice | 1001 | 2024-05-01 09:00:00 | 1003
81+
Alice | 1002 | 2024-05-01 11:00:00 | 1003
82+
Alice | 1003 | 2024-05-02 14:30:00 | 1003
83+
Bob | 1004 | 2024-05-01 08:30:00 | 1006
84+
Bob | 1005 | 2024-05-01 20:15:00 | 1006
85+
Bob | 1006 | 2024-05-03 10:00:00 | 1006
86+
Carol | 1007 | 2024-05-04 09:45:00 | 1007
87+
```
88+
89+
**Example 2. Peek 12 hours ahead within each customer**
90+
91+
```sql
92+
SELECT customer,
93+
order_id,
94+
order_time,
95+
amount,
96+
LAST_VALUE(amount) OVER (
97+
PARTITION BY customer
98+
ORDER BY order_time
99+
RANGE BETWEEN CURRENT ROW AND INTERVAL 12 HOUR FOLLOWING
100+
) AS last_amount_next_12h
101+
FROM orders_window_demo
102+
ORDER BY customer, order_time;
103+
```
104+
105+
Result:
106+
```
107+
customer | order_id | order_time | amount | last_amount_next_12h
108+
---------+----------+----------------------+--------+----------------------
109+
Alice | 1001 | 2024-05-01 09:00:00 | 120 | 135
110+
Alice | 1002 | 2024-05-01 11:00:00 | 135 | 135
111+
Alice | 1003 | 2024-05-02 14:30:00 | 125 | 125
112+
Bob | 1004 | 2024-05-01 08:30:00 | 90 | 105
113+
Bob | 1005 | 2024-05-01 20:15:00 | 105 | 105
114+
Bob | 1006 | 2024-05-03 10:00:00 | 95 | 95
115+
Carol | 1007 | 2024-05-04 09:45:00 | 80 | 80
116+
```
117+
118+
**Example 3. Skip nulls when scanning forward for the last sales rep**
119+
120+
```sql
121+
SELECT customer,
122+
order_id,
123+
sales_rep,
124+
LAST_VALUE(sales_rep) RESPECT NULLS OVER (
125+
PARTITION BY customer
126+
ORDER BY order_time
127+
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
128+
) AS last_rep_respect,
129+
LAST_VALUE(sales_rep) IGNORE NULLS OVER (
130+
PARTITION BY customer
131+
ORDER BY order_time
132+
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
133+
) AS last_rep_ignore
134+
FROM orders_window_demo
135+
ORDER BY customer, order_id;
136+
```
137+
138+
Result:
139+
```
140+
customer | order_id | sales_rep | last_rep_respect | last_rep_ignore
141+
---------+----------+-----------+------------------+-----------------
142+
Alice | 1001 | Erin | Glen | Glen
143+
Alice | 1002 | NULL | Glen | Glen
144+
Alice | 1003 | Glen | Glen | Glen
145+
Bob | 1004 | NULL | NULL | Kai
146+
Bob | 1005 | Kai | NULL | Kai
147+
Bob | 1006 | NULL | NULL | Kai
148+
Carol | 1007 | Lily | Lily | Lily
149+
```

0 commit comments

Comments
 (0)