What are window functions, and how do they differ from GROUP BY?
A window function computes a value across a set of rows — a window — without collapsing those rows into groups. GROUP BY summarises and reduces the row count; a window function summarises and keeps every row, adding the summary alongside the row's own values.
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
amount DECIMAL(10, 2) NOT NULL,
placed_on TEXT NOT NULL
);
INSERT INTO orders (id, customer_id, amount, placed_on) VALUES
(1, 1, 120.00, '2026-01-05'),
(2, 1, 340.50, '2026-01-20'),
(3, 2, 75.25, '2026-02-03'),
(4, 1, 90.00, '2026-02-14');
SELECT id, customer_id, amount,
SUM(amount) OVER (PARTITION BY customer_id) AS customer_total,
SUM(amount) OVER () AS grand_total
FROM orders
ORDER BY customer_id, id;Four rows come back, and every one of them is still an individual order. Ada's three orders each carry her customer total of 550.50; Grace's single order carries 75.25. All four carry the grand total of 625.75, which is the same value in every row.
The OVER clause is what makes it a window function, and it has three parts. PARTITION BY divides the rows into separate windows — without it, every row sees every other row. ORDER BY defines the order within the window, which matters for the order-sensitive functions like ROW_NUMBER, RANK, LAG and running totals. The frame specification, which you can omit for the defaults, defines exactly which rows within the partition are included.
The comparison with GROUP BY is the thing to have ready for an interview. With GROUP BY you write SELECT customer_id, SUM(amount) FROM orders GROUP BY customer_id and get one row per customer. With the window function you write SUM(amount) OVER (PARTITION BY customer_id) and get every order, each decorated with its customer's total. When you want to reduce, use GROUP BY; when you want to annotate, use a window.