Part of the SQL Engineering Handbook
Bridging syntax and real-world analytics. This module does not teach you what a window function is — Module 07 already did that. This module teaches you where, why, and how window functions are used inside real companies — in HR systems, sales pipelines, e-commerce platforms, banking cores, and finance departments.
Every SQL engineer eventually learns the syntax of ROW_NUMBER(), RANK(),
LAG(), and SUM() OVER (...). Very few are taught why an analytics
team would reach for one over the other, or what business question
each pattern actually answers.
That gap is why candidates who can recite window function syntax in an interview still struggle to write a query that solves an actual leadership request like:
Window functions are the backbone of modern analytics engineering because
they let you compare a row to its peers, its past, and its group —
without collapsing the dataset. Unlike GROUP BY, which flattens data
into summaries, window functions preserve row-level granularity while
attaching aggregate, ranking, and offset context to each row — exactly the
shape of data that feeds dashboards, leaderboards, cohort reports, and
anomaly-detection systems.
This module is organized around five business domains that, together, cover the vast majority of window function use cases you’ll encounter in industry: HR, Sales, E-Commerce, Banking, and Finance. One structural pattern — peer comparison, time comparison, or self comparison — repeats across all five; only the business vocabulary changes.
Learners who’ve completed Module 07 — Window Functions and are fluent, not just familiar, with:
ROW_NUMBER(), RANK(), DENSE_RANK(), NTILE()LAG(), LEAD()SUM(), AVG(), COUNT(), MIN(), MAX()
used with OVER (...)PARTITION BY and ORDER BY inside a window specificationROWS BETWEEN ... AND ...If any of these feel unfamiliar, revisit Module 07 before continuing — this module assumes fluency, not familiarity.
This module runs against the shared practice schema defined in
00_Schema:
mysql -u root -p your_database < ../00_Schema/01_CREATE_TABLES.sql
mysql -u root -p your_database < ../00_Schema/02_INSERT_DATA.sql
mysql -u root -p your_database < 01_HR_ANALYTICS.sql
Each domain’s .sql file runs independently — no setup is required between
chapters, though working through them in order (01 → 05) is strongly
recommended, since each chapter explicitly reuses a pattern from the one
before it.
| # | Domain | File | Diagram | Lines | Size |
|---|---|---|---|---|---|
| 01 | HR Analytics | .md · .sql |
hr-leaderboard-tiebreak.svg | 136 + 268 | 8.9 KB + 9.0 KB |
| 02 | Sales Analytics | .md · .sql |
sales-running-total-growth.svg | 134 + 232 | 8.3 KB + 7.7 KB |
| 03 | E-Commerce | .md · .sql |
ecommerce-customer-lifecycle.svg | 131 + 244 | 8.2 KB + 7.9 KB |
| 04 | Banking | .md · .sql |
banking-balance-outlier.svg | 129 + 241 | 9.3 KB + 8.7 KB |
| 05 | Finance | .md · .sql |
finance-ytd-variance.svg | 128 + 277 | 9.0 KB + 10.2 KB |
Totals: 5 .md files, 5 .sql files, 6 diagrams (5 topic diagrams + 1
banner) — 1,920 combined lines, ~87.2 KB of documentation and runnable SQL.
Each .md file explains the business context, KPIs, dashboards, and
reasoning; each paired .sql file contains the fully commented,
production-quality query chapter for that domain.
Every diagram in this module is a standalone SVG in
assets/diagrams/, embedded directly in its
corresponding chapter — no external image hosting, so they render correctly
on GitHub, cloned locally, or on GitHub Pages.
| # | Domain | Core Business Questions |
|---|---|---|
| 01 | HR Analytics | Who are our top performers? Who’s eligible for promotion? How is compensation distributed by department? |
| 02 | Sales Analytics | Who is our top salesperson this month? What’s our revenue trend? How does this quarter compare to last year? |
| 03 | E-Commerce | Who are our highest-LTV customers? What’s our repeat purchase rate? Which products dominate each category? |
| 04 | Banking | What are our largest transactions? Is this account behaving abnormally? What’s the running balance over time? |
| 05 | Finance | Are we over budget? What’s our running profit? How volatile is our expense variance month to month? |
By the end of this module, you will be able to:
ROW_NUMBER(), RANK(), and DENSE_RANK()
based on how ties should be handled in a business context.LAG() / LEAD() to build comparison reports (previous transaction,
next event, sequential gap analysis).| Function | Primary Use Case in This Module |
|---|---|
ROW_NUMBER() |
Unique sequencing, deduplication, “top N per group” |
RANK() |
Leaderboards where ties should share a rank and skip subsequent ranks |
DENSE_RANK() |
Leaderboards where ties should share a rank without skipping |
NTILE() |
Percentile buckets (e.g., performance quartiles, customer tiers) |
LAG() / LEAD() |
Period-over-period comparisons, transaction gap analysis, sequential trend detection |
SUM() OVER (...) |
Running totals, running balances, cumulative revenue |
AVG() OVER (...) |
Moving averages, smoothed trend lines, per-account statistical baselines |
COUNT() OVER (...) |
Group-level counts without collapsing row-level detail |
FIRST_VALUE() / LAST_VALUE() |
Baseline comparisons (e.g., first transaction vs. most recent) |
| Skill Category | What You Will Practice |
|---|---|
| Analytics Engineering | Translating KPIs into window function queries |
| Data Engineering | Writing performant, partition-aware SQL over large tables |
| Business Analysis | Understanding what each metric means to a stakeholder |
| SQL Architecture | Structuring multi-CTE, multi-scenario analytical queries |
| Interview Readiness | Explaining tradeoffs, not just producing correct output |
Work through the domains in order — each one reinforces the previous while introducing a new analytical pattern:
Each .sql file is organized into scenarios, and each scenario opens with
a business explanation before progressively more advanced queries.
| Domain | Estimated Time |
|---|---|
| HR Analytics | 60–75 minutes |
| Sales Analytics | 75–90 minutes |
| E-Commerce | 75–90 minutes |
| Banking | 60–75 minutes |
| Finance | 60–75 minutes |
| Total Module | ~6–7 hours |
Intermediate → Advanced. This module assumes syntax fluency and focuses entirely on application, judgment, and performance reasoning. Difficulty increases within each file as scenarios move from single- partition ranking to multi-metric, multi-window analytical reports.
ORDER BY inside OVER (...) when using
ranking or offset functions — undefined order produces non-deterministic
results.ROW_NUMBER() over RANK() / DENSE_RANK() when you need
exactly one row per group (“top 1 per department”), since ties in
RANK() can return more rows than expected.ROWS BETWEEN ...) when computing
running totals or moving averages — the default frame can silently
produce incorrect results when ORDER BY is present.WHERE clause.PARTITION BY and ORDER BY where possible;
window functions still benefit heavily from sort-friendly access paths.RANK() where the business wants exactly N rows per group — ties
can silently return more than N.SUM() OVER (...) always
returns the full partition total.SELECT’s
WHERE clause — this requires a CTE or subquery.Window functions in this module map directly to systems you will build or maintain on the job:
For Data Analytics — you’ll independently translate a stakeholder’s question into a correct, efficient window function query, the single most common analytics interview and on-the-job task.
For Data Engineering — you’ll understand the performance cost of partitioning and ordering at scale, which directly informs how you design tables, indexes, and materialized views feeding these queries.
For Analytics Engineering — you’ll be able to build reusable, well-documented SQL models (dbt-style) where window functions form the core transformation logic for a metrics layer.
For SQL Interviews — you’ll be ready for the most commonly asked interview pattern across FAANG and mid-size tech companies — “Write a query to find the top N per group” — along with its many variations (running totals, YoY growth, gap analysis).
.sql file runs cleanly against the shared
00_Schema setup.md file follows a consistent template: Introduction →
Business Background → KPIs → Dashboards → Business Problems → Why
Window Functions Are Needed → Functions Used → SQL Concepts
Reinforced → Performance Notes → Common Mistakes → Interview
Questions → Summary → Further Practiceassets/diagrams/ — rendered inline, not just
linkedThis module is one part of the full SQL Engineering Handbook — a
16-module, progressively-built curriculum sharing a single practice schema
(00_Schema) end to end.
| # | Module | Contents | Status |
|---|---|---|---|
| — | Resources | Books, blogs, docs, certifications, communities, datasets | ✅ |
| 00 | Schema | Practice database DDL, seed data, and ERD used by every later module | ✅ |
| 01 | Fundamentals | SELECT, WHERE, ORDER BY, LIMIT, aliasing |
✅ |
| 02 | Aggregations | COUNT, SUM, AVG, MIN/MAX, GROUP BY, HAVING |
✅ |
| 03 | Joins | Inner, left, right, full, cross, self joins + performance audit | ✅ |
| 04 | Subqueries | Scalar, correlated, EXISTS, derived tables, subquery-to-join rewrites |
✅ |
| 05 | CASE WHEN | Conditional logic and business-rule encoding | ✅ |
| 06 | CTEs | Common Table Expressions, staged pipelines, business classification | ✅ |
| 07 | Window Functions | ROW_NUMBER, RANK, LAG/LEAD, PARTITION BY |
✅ |
| 08 | Window Business Cases (this module) | HR, Sales, E-Commerce, Banking, and Finance window-function case studies | ✅ |
| 09 | Date Functions | Date arithmetic, formatting, range queries | ✅ |
| 10 | String Functions | String manipulation and data cleaning | ✅ |
| 11 | NULL Handling & Data Cleaning | COALESCE, NULLIF, data-quality patterns |
✅ |
| 12 | Advanced Aggregations | Conditional and multi-level aggregation | ✅ |
| 13 | Set Operators | UNION, INTERSECT, EXCEPT, reconciliation queries |
✅ |
| 14 | Views | Views, security, updatable views, performance | ✅ |
| 15 | Indexes | B-Tree, composite, covering indexes, reading EXPLAIN |
✅ |
⬅ 07 — Window Functions · Handbook Home · 09 — Date Functions ➡