-
Basic usage:
SELECT name, salary, LAST_VALUE(salary) OVER (PARTITION BY salary ) as min_salary
FROM VALUES
('Eric', 1, 28000),
('Alex', 1, 32000),
('Felix', 2, 21000),
('Frank', 1, 30000),
('Tom', 2, 23000),
('Jane', 3, 29000),
('Jeff', 3, 35000),
('Paul', 2, 29000),
('Charles', 2, 23000),
('Charles F', 2, 23000),
('null',4,null),
('NotNull',4,23000)
AS tab(name, dep_no, salary);
+-----------+--------+------------+
| name | salary | min_salary |
+-----------+--------+------------+
| null | null | null |
| Eric | 28000 | 28000 |
| Jeff | 35000 | 35000 |
| Frank | 30000 | 30000 |
| Felix | 21000 | 21000 |
| Tom | 23000 | 23000 |
| Charles | 23000 | 23000 |
| Charles F | 23000 | 23000 |
| NotNull | 23000 | 23000 |
| Jane | 29000 | 29000 |
| Paul | 29000 | 29000 |
| Alex | 32000 | 32000 |
+-----------+--------+------------+
-
Ignore NULL values: In this example, we will ignore employees with NULL salaries.
SELECT name, salary, LAST_VALUE(salary,true) OVER (PARTITION BY salary ) as min_salary
FROM VALUES
('Eric', 1, 28000),
('Alex', 1, 32000),
('Felix', 2, 21000),
('Frank', 1, 30000),
('Tom', 2, 23000),
('Jane', 3, 29000),
('Jeff', 3, 35000),
('Paul', 2, 29000),
('Charles', 2, 23000),
('Charles F', 2, 23000),
('null',4,null),
('NotNull',4,23000)
AS tab(name, dep_no, salary);
+-----------+--------+------------+
| name | salary | min_salary |
+-----------+--------+------------+
| null | null | null |
| Eric | 28000 | 28000 |
| Jeff | 35000 | 35000 |
| Frank | 30000 | 30000 |
| Felix | 21000 | 21000 |
| Tom | 23000 | 23000 |
| Charles | 23000 | 23000 |
| Charles F | 23000 | 23000 |
| NotNull | 23000 | 23000 |
| Jane | 29000 | 29000 |
| Paul | 29000 | 29000 |
| Alex | 32000 | 32000 |
+-----------+--------+------------+
-
Using in conjunction with ORDER BY:
SELECT name, salary, LAST_VALUE(salary) OVER (PARTITION BY dep_no ORDER BY dep_no DESC) as min_salary
FROM VALUES
('Eric', 1, 28000),
('Alex', 1, 32000),
('Felix', 2, 21000),
('Frank', 1, 30000),
('Tom', 2, 23000),
('Jane', 3, 29000),
('Jeff', 3, 35000),
('Paul', 2, 29000),
('Charles', 2, 23000),
('Charles F', 2, 23000),
('null',4,null),
('NotNull',4,23000)
AS tab(name, dep_no, salary);
+-----------+--------+------------+
| name | salary | min_salary |
+-----------+--------+------------+
| Jane | 29000 | 35000 |
| Jeff | 35000 | 35000 |
| Eric | 28000 | 30000 |
| Alex | 32000 | 30000 |
| Frank | 30000 | 30000 |
| Felix | 21000 | 23000 |
| Tom | 23000 | 23000 |
| Paul | 29000 | 23000 |
| Charles | 23000 | 23000 |
| Charles F | 23000 | 23000 |
| null | null | 23000 |
| NotNull | 23000 | 23000 |
+-----------+--------+------------+
-
Using Window Functions:When you need to apply the LAST function to the entire dataset, you can use the ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING clause.
SELECT name, salary, LAST_VALUE(salary, true) OVER (ORDER BY salary ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as global_min_salary
FROM VALUES
('Eric', 1, 28000),
('Alex', 1, 32000),
('Felix', 2, 21000),
('Frank', 1, 30000),
('Tom', 2, 23000),
('Jane', 3, 29000),
('Jeff', 3, 35000),
('Paul', 2, 29000),
('Charles', 2, 23000),
('Charles F', 2, 23000),
('null',4,null),
('NotNull',4,23000)
AS tab(name, dep_no, salary);
+-----------+--------+-------------------+
| name | salary | global_min_salary |
+-----------+--------+-------------------+
| null | null | 35000 |
| Felix | 21000 | 35000 |
| Tom | 23000 | 35000 |
| Charles | 23000 | 35000 |
| Charles F | 23000 | 35000 |
| NotNull | 23000 | 35000 |
| Eric | 28000 | 35000 |
| Jane | 29000 | 35000 |
| Paul | 29000 | 35000 |
| Frank | 30000 | 35000 |
| Alex | 32000 | 35000 |
| Jeff | 35000 | 35000 |
+-----------+--------+-------------------+