DevBolt
Processed in your browser. Your data never leaves your device.

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.

Samples:

Loading SQLite engine…

SQLite dialect • Multiple statements supported508 chars
Run a query to see results

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