Home/Learn/SQL/Window Functions vs GROUP BY

Window Functions vs GROUP BY

Intermediate
Window Functions

GROUP BY collapses many rows into one aggregate row per group; window functions keep all rows while adding computed values — choose based on whether you need row-level detail alongside aggregates.

Overview

The fundamental trade-off: GROUP BY is for pure aggregation reports where detail rows are not needed; window functions are for queries where individual row context must be preserved. A common requirement — "show each order alongside the customer's total order count" — is impossible with plain GROUP BY because grouping collapses the order rows. Window functions solve this directly. The two approaches can also be combined in the same query: GROUP BY first to produce a summary, then apply a window function over that summary. Window function results cannot appear in WHERE; use a CTE or subquery.

The Core Difference: Row Preservation

When you need individual row details AND aggregate values together in the same output, GROUP BY alone cannot deliver — it eliminates the detail rows. A window function provides both in a single pass.

SQL — row-level detail + aggregate impossible with GROUP BY
-- Requirement: list every order with the customer's total order count

-- WRONG attempt with GROUP BY: loses individual order rows
SELECT user_id, COUNT(*) AS total_orders
FROM orders
GROUP BY user_id;
-- Can't include order id, amount, etc. — they would need to be aggregated too

-- CORRECT: window function preserves every row
SELECT
    o.id           AS order_id,
    o.user_id,
    o.amount,
    o.status,
    o.created_at,
    COUNT(*)   OVER (PARTITION BY o.user_id) AS user_total_orders,
    SUM(amount) OVER (PARTITION BY o.user_id) AS user_total_spent
FROM orders o;

Combining GROUP BY and Window Functions

GROUP BY and window functions can appear in the same query. GROUP BY runs first, collapsing rows, then window functions operate on the collapsed result set.

SQL — GROUP BY + window function in the same query
-- Department summary: average salary vs company-wide average
-- GROUP BY first collapses employees to department level,
-- then window function compares each department avg to company avg.
SELECT
    d.name                      AS department,
    COUNT(e.id)                 AS headcount,
    ROUND(AVG(e.salary), 2)     AS dept_avg_salary,
    ROUND(
        AVG(AVG(e.salary)) OVER (),   -- window over the grouped rows
        2
    )                           AS company_avg_salary,
    ROUND(
        100.0 * AVG(e.salary)
              / AVG(AVG(e.salary)) OVER () - 100,
        1
    )                           AS pct_vs_company_avg
FROM employees e
JOIN departments d ON d.id = e.department_id
GROUP BY d.id, d.name
ORDER BY dept_avg_salary DESC;

Filtering on Window Results (CTE Pattern)

Window function results are computed after WHERE/GROUP BY/HAVING, so they cannot be referenced in those clauses. Always filter on window values via a CTE or derived table.

SQL — CTE to filter on window function result
-- Show employees who earn more than the company average (window can't go in WHERE)
-- WRONG:
SELECT name, salary,
       AVG(salary) OVER () AS avg_salary
FROM employees
WHERE salary > AVG(salary) OVER ();  -- ERROR

-- CORRECT via CTE:
WITH emp_with_avg AS (
    SELECT
        name,
        department_id,
        salary,
        AVG(salary) OVER ()                              AS company_avg,
        AVG(salary) OVER (PARTITION BY department_id)   AS dept_avg
    FROM employees
)
SELECT name, department_id, salary, company_avg, dept_avg
FROM emp_with_avg
WHERE salary > company_avg;

Key Points to Remember

  • 1GROUP BY collapses rows: one output row per group. Window functions preserve all rows: every input row appears in output.
  • 2Use GROUP BY for pure summaries (report tables). Use window functions when you need both detail rows and group-level metrics together.
  • 3GROUP BY and window functions can coexist: GROUP BY runs first, then the window function operates on the aggregated rows.
  • 4You cannot reference a window function alias in WHERE, HAVING, or GROUP BY — wrap in a CTE or subquery.
  • 5Window functions add computational cost; avoid applying them on large intermediate result sets without appropriate indexes.

Interview Questions

Sign in to ask Aria
1

Why can't you show each order with the customer's total order count using GROUP BY alone?

MediumUber
2

Write a query showing each employee's salary alongside the average salary for their department in a single query.

MediumAmazon
3

Can GROUP BY and window functions be used in the same query? If so, which runs first?

HardGoogle
4

How do you filter rows based on the result of a window function?

MediumSwiggy

Ask Aria about Window Functions vs GROUP BY

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…