SQL Window Functions — Interactive Tutorial
Window functions perform calculations across a set of rows related to the current row — without collapsing results like GROUP BY. Practice ROW_NUMBER, RANK, LAG, LEAD, running totals, and more in a real database.
Loading SQLite engine…
SQLite Quick Reference
Data Definition
CREATE TABLE t ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, val REAL DEFAULT 0 ); ALTER TABLE t ADD col TEXT; DROP TABLE IF EXISTS t;
Queries
SELECT * FROM t WHERE x > 5; SELECT a, COUNT(*) FROM t GROUP BY a HAVING COUNT(*) > 1; SELECT * FROM t1 JOIN t2 ON t1.id = t2.fk;
Data Manipulation
INSERT INTO t (a, b) VALUES (1, 'x'), (2, 'y'); UPDATE t SET a = 10 WHERE id = 1; DELETE FROM t WHERE a IS NULL;
Functions
COUNT, SUM, AVG, MIN, MAX LENGTH, UPPER, LOWER, TRIM SUBSTR, REPLACE, INSTR COALESCE, NULLIF, IIF date, time, datetime, strftime
Window Functions
ROW_NUMBER() OVER ( PARTITION BY col ORDER BY col2 ) RANK, DENSE_RANK, NTILE LAG, LEAD, FIRST_VALUE
CTEs & Subqueries
WITH cte AS ( SELECT a, COUNT(*) AS cnt FROM t GROUP BY a ) SELECT * FROM cte WHERE cnt > 1;
How It Works
In-Browser SQLite
This playground runs a complete SQLite database engine in your browser using WebAssembly. No server required — your queries and data never leave your device.
Full SQL Support
Supports CREATE, INSERT, UPDATE, DELETE, SELECT with JOINs, subqueries, CTEs, window functions, aggregations, indexes, views, triggers, and more.
Multiple Statements
Run multiple SQL statements in sequence separated by semicolons. Each statement's results display separately with execution timing.
Schema Inspector
Click "Schema" to view all tables in your database with their CREATE TABLE definitions. Useful for checking column names and types.
Powered by sql.js (SQLite compiled to WebAssembly). Your SQL and data are processed entirely in your browser — nothing is sent to any server. Database resets when you refresh the page.
What Are Window Functions?
Window functions compute a value for each row based on a 'window' of related rows. Unlike aggregate functions with GROUP BY, window functions don't collapse rows — you get the computed value alongside every row. The OVER clause defines the window: PARTITION BY groups rows, ORDER BY sequences them within each partition.
ROW_NUMBER, RANK, and DENSE_RANK
These ranking functions assign numbers to rows within a partition. ROW_NUMBER gives unique sequential numbers (1,2,3,4). RANK leaves gaps for ties (1,2,2,4). DENSE_RANK has no gaps (1,2,2,3). Common use: top-N per group queries.
SELECT name, department, salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num,
RANK() OVER (ORDER BY salary DESC) AS salary_rank
FROM employees;Running Totals and Moving Averages
Use SUM() or AVG() with OVER to compute running totals or moving averages. The frame clause (ROWS BETWEEN) controls which rows are included: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW for a running total, ROWS BETWEEN 2 PRECEDING AND CURRENT ROW for a 3-row moving average.
SELECT sale_date, amount,
SUM(amount) OVER (ORDER BY sale_date) AS running_total,
AVG(amount) OVER (
ORDER BY sale_date
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS moving_avg_3
FROM sales;LAG and LEAD for Row Comparisons
LAG(column, offset) accesses a previous row's value; LEAD(column, offset) accesses a following row's value. These are essential for calculating period-over-period changes: LAG(revenue, 1) gives last month's revenue so you can compute month-over-month growth without self-joins.
SELECT month, revenue,
LAG(revenue, 1) OVER (ORDER BY month) AS prev_month,
revenue - LAG(revenue, 1) OVER (ORDER BY month) AS growth
FROM monthly_sales;Frequently Asked Questions
Does SQLite support window functions?
Yes, SQLite has full window function support since version 3.25.0 (2018). All standard window functions work: ROW_NUMBER, RANK, DENSE_RANK, NTILE, LAG, LEAD, FIRST_VALUE, LAST_VALUE, NTH_VALUE, plus aggregate functions (SUM, AVG, COUNT, MIN, MAX) used with OVER.
What is the difference between PARTITION BY and GROUP BY?
GROUP BY collapses multiple rows into one summary row per group. PARTITION BY in a window function defines groups for the calculation but keeps all original rows in the output. You get the aggregate value alongside every detail row.
When should I use window functions instead of GROUP BY?
Use window functions when you need both detail and aggregate data in the same query — for example, showing each employee's salary alongside their department average. They're also essential for ranking (top N per group), running totals, and comparing consecutive rows (LAG/LEAD).
Related Inspect Tools
LLM Token Counter
Count tokens and estimate API costs for GPT-4o, Claude, Gemini, and other LLMs with BPE tokenization
AI Model Comparison
Compare 23 AI models (Claude 4.6, GPT-4.1, Gemini 3) + 5 coding IDEs (Cursor, Copilot, Windsurf, Kiro, Antigravity) — pricing, context windows, capabilities
JSON Visualizer
Visualize JSON as an interactive tree — collapsible nodes, search, path copy, depth controls, and data statistics
Git Diff Viewer
Paste unified diff output from git diff and view it with syntax highlighting, line numbers, and side-by-side or inline display