SQLite Joins, CTEs, and Window Functions Cheatsheet

JOIN patterns, recursive CTEs, ranking functions, running totals, and analytical SQL patterns for SQLite.

View
StandardDetailedCompact
Export
Copy the compact sheet, download it, or print it.
Download
`D` dense toggle · `C` copy all

Join tables

Combine rows across related tables.

Use an INNER JOIN

Return rows that match in both tables.

sqlANYsqlitejoininner join
sql
SELECT p.id, p.title, u.email
FROM posts p
JOIN users u ON u.id = p.user_id;

The most common join pattern for parent-child data.

Use a LEFT JOIN

Keep parent rows even if the child is missing.

sqlANYsqliteleft join
sql
SELECT u.id, u.email, p.title
FROM users u
LEFT JOIN posts p ON p.user_id = u.id;

Useful when optional related data should not hide the main row.

Join and aggregate

Count child rows per parent.

sqlANYsqlitegroup bycount
sql
SELECT u.id, u.email, COUNT(p.id) AS post_count
FROM users u
LEFT JOIN posts p ON p.user_id = u.id
GROUP BY u.id, u.email;

A practical dashboard query pattern.

CTEs and window functions

Write readable multi-step queries and analytic calculations.

Use a CTE to stage a subquery

Name an intermediate result set.

sqlANYsqlitectewith
sql
WITH recent_posts AS (
  SELECT * FROM posts WHERE created_at >= date('now', '-7 day')
)
SELECT COUNT(*) FROM recent_posts;

CTEs improve readability for multi-step transformations.

Use a recursive CTE

Walk a hierarchy such as categories or folders.

sqlANYsqliterecursivehierarchy
sql
WITH RECURSIVE category_tree(id, name, parent_id, depth) AS (
  SELECT id, name, parent_id, 0 FROM categories WHERE parent_id IS NULL
  UNION ALL
  SELECT c.id, c.name, c.parent_id, ct.depth + 1
  FROM categories c
  JOIN category_tree ct ON c.parent_id = ct.id
)
SELECT * FROM category_tree;

Recursive CTEs are the go-to pattern for tree traversal in SQLite.

Assign row numbers

Rank rows within an ordered result.

sqlANYsqliterow_numberwindow
sql
SELECT id, email, ROW_NUMBER() OVER (ORDER BY created_at DESC) AS row_num
FROM users;

Useful for ordered reports and deterministic pagination helpers.

Compute a running total

Use SUM() OVER for cumulative metrics.

sqlANYsqliterunning totalsum over
sql
SELECT created_at,
       amount,
       SUM(amount) OVER (ORDER BY created_at) AS running_total
FROM invoices;

Great for revenue charts and time-series analytics.

Rank rows by score

Assign rank values with ties.

sqlANYsqlitedense_rankanalytics
sql
SELECT player_id, score,
       DENSE_RANK() OVER (ORDER BY score DESC) AS leaderboard_rank
FROM scores;

Useful for leaderboards and scoring systems.

Recommended next

No recommendations yet.