{
    "slug": "sql_window_functions",
    "term": "SQL Window Functions",
    "category": "database",
    "difficulty": "intermediate",
    "short": "Window functions (ROW_NUMBER, RANK, LAG, LEAD, SUM OVER) perform calculations across a set of rows related to the current row without collapsing them into a single aggregate — enabling rankings, running totals, and comparisons within result sets.",
    "long": "Unlike GROUP BY aggregates which reduce multiple rows to one, window functions operate over a defined frame of rows (the window) and return a value for every input row. The OVER clause defines the window via PARTITION BY (grouping), ORDER BY (row order within partition), and an optional ROWS/RANGE frame. Common functions include ROW_NUMBER (unique sequential rank), RANK/DENSE_RANK (tied ranks), LAG/LEAD (access previous/next row), and aggregate functions like SUM, AVG, MAX applied as running calculations. Window functions execute after WHERE and GROUP BY but before ORDER BY and LIMIT, making them composable with other clauses. In PHP applications they eliminate the need for multiple round trips or application-side sorting and ranking logic.",
    "aliases": [],
    "tags": [
        "sql",
        "database",
        "query-optimisation",
        "analytics"
    ],
    "misconception": "Window functions do not filter or reduce rows — every input row produces an output row, even when calculating aggregates like SUM OVER.",
    "why_it_matters": "Replacing application-side ranking and running-total loops with a single window function query reduces round trips and moves computation to where the data lives — orders of magnitude faster on large result sets.",
    "common_mistakes": [
        "Omitting ORDER BY inside OVER for RANK or ROW_NUMBER — the result is non-deterministic.",
        "Using PARTITION BY when GROUP BY is intended — window functions do not reduce rows, so counts stay per-row.",
        "Trying to filter on a window function alias in WHERE — use a subquery or CTE; window functions are not available in WHERE."
    ],
    "when_to_use": [
        "Use ROW_NUMBER or RANK when you need per-partition rankings without losing the underlying rows (top N per category).",
        "Use LAG/LEAD to compare a row with its predecessor or successor in a time series without a self-join.",
        "Use SUM/AVG OVER for running totals, moving averages, and cumulative distributions in reporting queries."
    ],
    "avoid_when": [
        "Avoid window functions when a simple GROUP BY aggregate answers the question — window functions have higher planning cost.",
        "Do not use them on tables without an appropriate index on the PARTITION BY and ORDER BY columns — the sort cost dominates."
    ],
    "related": [
        "query_optimization",
        "database_indexes",
        "db_cte"
    ],
    "prerequisites": [],
    "refs": [
        "https://www.postgresql.org/docs/current/tutorial-window.html"
    ],
    "bad_code": "-- Application-side ranking: N+1 queries\n$users = $db->query('SELECT * FROM users ORDER BY score DESC');\n$rank = 1;\nforeach ($users as $u) {\n    $u['rank'] = $rank++; // sequential but ignores ties\n}",
    "good_code": "-- Single query with window function:\nSELECT\n    id,\n    name,\n    score,\n    RANK() OVER (ORDER BY score DESC) AS rank,\n    SUM(score) OVER ()               AS total_score\nFROM users;",
    "example_note": "The bad example loops in PHP assigning sequential ranks — it ignores ties and requires loading every user. The window function ranks in one query, handles ties correctly, and adds a running total column at no extra cost.",
    "created": "2026-03-31",
    "updated": "2026-03-31",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/sql_window_functions",
        "html_url": "https://codeclaritylab.com/glossary/sql_window_functions",
        "json_url": "https://codeclaritylab.com/glossary/sql_window_functions.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[SQL Window Functions](https://codeclaritylab.com/glossary/sql_window_functions) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/sql_window_functions"
            }
        }
    }
}