Advertisement
❮ Previous: SQL CTEs Next: SQL Database (Overview) ❯

SQL Window Functions

SELECT 
    DepartmentID,
    FirstName,
    Salary,
    ROW_NUMBER() OVER (PARTITION BY DepartmentID ORDER BY Salary DESC) AS RowNum,
    RANK()       OVER (PARTITION BY DepartmentID ORDER BY Salary DESC) AS RankNum,
    DENSE_RANK() OVER (PARTITION BY DepartmentID ORDER BY Salary DESC) AS# SQL Window Functions

A **window function** performs calculations across a set of table rows that are related to the current row. Unlike aggregate functions (`SUM`, `AVG`, `COUNT`), which collapse multiple rows into a single summary row using `GROUP BY`, window functions retain the individual identity of each row while computing aggregate or ranking values alongside it.

The OVER() Clause

The defining feature of a window function is the OVER() clause. It defines the "window" of rows that the function operates on.

Syntax

function_name(expression) OVER (
    [PARTITION BY partition_column]
    [ORDER BY sort_column]
    [ROWS|RANGE frame_spec]
)

Advertisement

How Window Functions Differ from Aggregates

               AGGREGATE FUNCTION (GROUP BY)
+------------+------------+           +------------+------------+
| Department | Salary     |           | Department | SUM(Salary)|
+------------+------------+           +------------+------------+
| Sales      | 5000       |  ----->   | Sales      | 11000      |
| Sales      | 6000       |           | IT         | 15000      |
| IT         | 7000       |           +------------+------------+
| IT         | 8000       |           (Collapses 4 rows into 2)
+------------+------------+

               WINDOW FUNCTION (OVER PARTITION BY)
+------------+------------+---------------------------------+
| Department | Salary     | SUM(Salary) OVER (PARTITION...) |
+------------+------------+---------------------------------+
| Sales      | 5000       | 11000                           |
| Sales      | 6000       | 11000                           |
| IT         | 7000       | 15000                           |
| IT         | 8000       | 15000                           |
+------------+------------+---------------------------------+
(Keeps all 4 rows intact)


Advertisement

Categories of Window Functions

1. Ranking Functions

Ranking functions assign a sequential integer or rank to each row based on its ordering within a partition.

Example: Comparing Ranking Functions

SELECT 
    EmployeeID,
    Department,
    Salary,
    ROW_NUMBER() OVER (PARTITION BY Department ORDER BY Salary DESC) AS RowNum,
    RANK()       OVER (PARTITION BY Department ORDER BY Salary DESC) AS RankNum,
    DENSE_RANK() OVER (PARTITION BY Department ORDER BY Salary DESC) AS DenseRankNum
FROM Employees;

Output:

EmployeeID Department Salary RowNum RankNum DenseRankNum
101 Sales 8000 1 1 1
102 Sales 8000 2 1 1
103 Sales 6000 3 3 2
104 Sales 5000 4 4 3

2. Value / Analytic Functions

Value functions allow you to access data from other rows in the result set relative to the current row without performing a self-join.

Example: Calculating Year-Over-Year Growth with LAG()

SELECT 
    SalesYear,
    TotalRevenue,
    LAG(TotalRevenue, 1) OVER (ORDER BY SalesYear) AS PreviousYearRevenue,
    TotalRevenue - LAG(TotalRevenue, 1) OVER (ORDER BY SalesYear) AS YoYChange
FROM AnnualSales;

3. Aggregate Window Functions

Standard aggregate functions (SUM, AVG, COUNT, MIN, MAX) can be turned into window functions by adding an OVER() clause.

Example: Running Total (Cumulative Sum)

When an ORDER BY clause is included inside OVER() with an aggregate function, SQL defaults to computing a cumulative running total from the first row of the partition up to the current row.

SELECT 
    OrderID,
    OrderDate,
    TotalAmount,
    SUM(TotalAmount) OVER (ORDER BY OrderDate) AS RunningTotal
FROM Orders;

Advertisement

Window Frames: ROWS vs. RANGE

When using an ORDER BY clause inside OVER(), you can refine the exact subset of rows included in the window using frame specifications.

Common Frame Options:

Example: 3-Period Moving Average

SELECT 
    SalesDate,
    DailyRevenue,
    AVG(DailyRevenue) OVER (
        ORDER BY SalesDate 
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
    ) AS MovingAvg3Day
FROM DailySales;
❮ Previous: SQL CTEs Next: SQL Database (Overview) ❯
Advertisement