---
title: Window functions
tags: postgresql, yoctol, workshop
---
# Window functions
https://www.postgresql.org/docs/13/functions-window.html
## Syntax
The syntax of a window function call is one of the following:
```sql
function_name ([expression [, expression ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER window_name
function_name ([expression [, expression ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER ( window_definition )
function_name ( * ) [ FILTER ( WHERE filter_clause ) ] OVER window_name
function_name ( * ) [ FILTER ( WHERE filter_clause ) ] OVER ( window_definition )
```
where window_definition has the syntax
```sql
[ existing_window_name ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ frame_clause ]
```
The optional frame_clause can be one of
```sql
{ RANGE | ROWS | GROUPS } frame_start [ frame_exclusion ]
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end [ frame_exclusion ]
```
where frame_start and frame_end can be one of
```sql
UNBOUNDED PRECEDING
offset PRECEDING
CURRENT ROW
offset FOLLOWING
UNBOUNDED FOLLOWING
```
and frame_exclusion can be one of
```sql
EXCLUDE CURRENT ROW
EXCLUDE GROUP
EXCLUDE TIES
EXCLUDE NO OTHERS
```
## setup
```sql
CREATE TABLE product_groups (
group_id serial PRIMARY KEY,
group_name VARCHAR (255) NOT NULL
);
CREATE TABLE products (
product_id serial PRIMARY KEY,
product_name VARCHAR (255) NOT NULL,
price DECIMAL (11, 2),
group_id INT NOT NULL,
FOREIGN KEY (group_id) REFERENCES product_groups (group_id)
);
INSERT INTO product_groups (group_name)
VALUES
('Smartphone'),
('Laptop'),
('Tablet');
INSERT INTO products (product_name, group_id, price)
VALUES
('Microsoft Lumia', 1, 200),
('HTC One', 1, 400),
('Nexus', 1, 500),
('iPhone', 1, 900),
('HP Elite', 2, 1200),
('Lenovo Thinkpad', 2, 700),
('Sony VAIO', 2, 700),
('Dell Vostro', 2, 800),
('iPad', 3, 700),
('Kindle Fire', 3, 150),
('Samsung Galaxy Tab', 3, 200);
```
## row_number ()
```sql
SELECT
row_number () over (PARTITION by price),
*
FROM
products;
```
## rank ()
```sql
SELECT
rank () over (PARTITION by group_id order by price),
*
FROM
products;
```
## dense_rank ()
```sql
SELECT
dense_rank () over (PARTITION by group_id order by price),
*
FROM
products;
```
## percent_rank ()
```sql
SELECT
percent_rank () over (PARTITION by group_id order by price),
*
FROM
products;
```
## cume_dist ()
https://zh.wikipedia.org/wiki/%E7%B4%AF%E7%A7%AF%E5%88%86%E5%B8%83%E5%87%BD%E6%95%B0
```sql
SELECT
cume_dist () OVER (PARTITION BY group_id ORDER BY price),
*
FROM
products;
```
## ntile ()
```sql
SELECT
ntile (2) OVER (PARTITION BY group_id),
*
FROM
products;
```
```sql
SELECT
ntile (2) OVER (PARTITION BY price),
*
FROM
products;
```
## lag ()
```sql
SELECT
lag (price, 1) OVER (PARTITION BY group_id order by price),
*
FROM
products;
```
```sql
SELECT
product_name,
group_name,
price,
price - LAG (price, 1) OVER (
PARTITION BY group_name
ORDER BY
price
) AS price_diff
FROM
products
INNER JOIN product_groups USING (group_id);
```
## lead ()
```sql
SELECT
lead (price, 1) OVER (PARTITION BY group_id order by price),
*
FROM
products;
```
## first_value () last_value ()
```sql
SELECT
first_value (price) OVER (PARTITION BY group_id order by price),
*
FROM
products;
```
## nth_value ()
```sql
SELECT
nth_value (price, 3) OVER (PARTITION BY group_id order by price),
*
FROM
products;
```
refs:
https://www.postgresqltutorial.com/postgresql-window-function/
https://www.2ndquadrant.com/en/blog/window-functions-time-series-iot-analytics-postgres-bdr/
https://blog.jooq.org/2015/05/12/use-this-neat-window-function-trick-to-calculate-time-differences-in-a-time-series/
https://www.maxlist.xyz/2020/06/05/postgresql-interview-questions/#%E4%BA%8C_%E9%80%9A%E7%94%A8%E8%A1%A8%E9%81%94%E5%BC%8F_Common_Table_Expressions