home / skills / 0xdarkmatter / claude-mods / sql-patterns

sql-patterns skill

/skills/sql-patterns

This skill helps you write and optimize SQL queries using common patterns, CTEs, and window functions for faster data retrieval.

npx playbooks add skill 0xdarkmatter/claude-mods --skill sql-patterns

Review the files below or copy the command above to add this skill to your agents.

Files (5)
SKILL.md
2.5 KB
---
name: sql-patterns
description: "Quick reference for common SQL patterns, CTEs, window functions, and indexing strategies. Triggers on: sql patterns, cte example, window functions, sql join, index strategy, pagination sql."
allowed-tools: "Read Write"
---

# SQL Patterns

Quick reference for common SQL patterns.

## CTE (Common Table Expressions)

```sql
WITH active_users AS (
    SELECT id, name, email
    FROM users
    WHERE status = 'active'
)
SELECT * FROM active_users WHERE created_at > '2024-01-01';
```

### Chained CTEs

```sql
WITH
    active_users AS (
        SELECT id, name FROM users WHERE status = 'active'
    ),
    user_orders AS (
        SELECT user_id, COUNT(*) as order_count
        FROM orders GROUP BY user_id
    )
SELECT u.name, COALESCE(o.order_count, 0) as orders
FROM active_users u
LEFT JOIN user_orders o ON u.id = o.user_id;
```

## Window Functions (Quick Reference)

| Function | Use |
|----------|-----|
| `ROW_NUMBER()` | Unique sequential numbering |
| `RANK()` | Rank with gaps (1, 2, 2, 4) |
| `DENSE_RANK()` | Rank without gaps (1, 2, 2, 3) |
| `LAG(col, n)` | Previous row value |
| `LEAD(col, n)` | Next row value |
| `SUM() OVER` | Running total |
| `AVG() OVER` | Moving average |

```sql
SELECT
    date,
    revenue,
    LAG(revenue, 1) OVER (ORDER BY date) as prev_day,
    SUM(revenue) OVER (ORDER BY date) as running_total
FROM daily_sales;
```

## JOIN Reference

| Type | Returns |
|------|---------|
| `INNER JOIN` | Only matching rows |
| `LEFT JOIN` | All left + matching right |
| `RIGHT JOIN` | All right + matching left |
| `FULL JOIN` | All rows, NULL where no match |

## Pagination

```sql
-- OFFSET/LIMIT (simple, slow for large offsets)
SELECT * FROM products ORDER BY id LIMIT 20 OFFSET 40;

-- Keyset (fast, scalable)
SELECT * FROM products WHERE id > 42 ORDER BY id LIMIT 20;
```

## Index Quick Reference

| Index Type | Best For |
|------------|----------|
| B-tree | Range queries, ORDER BY |
| Hash | Exact equality only |
| GIN | Arrays, JSONB, full-text |
| Covering | Avoid table lookup |

## Anti-Patterns

| Mistake | Fix |
|---------|-----|
| `SELECT *` | List columns explicitly |
| `WHERE YEAR(date) = 2024` | `WHERE date >= '2024-01-01'` |
| `NOT IN` with NULLs | Use `NOT EXISTS` |
| N+1 queries | Use JOIN or batch |

## Additional Resources

For detailed patterns, load:
- `./references/window-functions.md` - Complete window function patterns
- `./references/indexing-strategies.md` - Index types, covering indexes, optimization

Overview

This skill is a compact reference for common SQL patterns, including CTEs, window functions, joins, pagination, and indexing strategies. It delivers clear examples and quick rules-of-thumb to speed up query writing and optimization. Use it to validate patterns, avoid anti-patterns, and choose appropriate indexes. The content is focused on practical, copy-pasteable snippets.

How this skill works

The skill provides short, annotated examples for common tasks: building CTEs, chaining CTEs, using window functions, and applying joins and pagination. It lists index types and their ideal use cases, plus common anti-patterns with concise fixes. You can quickly look up the right pattern, adapt the SQL sample, and apply best practices to improve performance and readability.

When to use it

  • Composing complex queries that benefit from CTEs or chained CTEs
  • Implementing analytics or running row-based calculations with window functions
  • Choosing a pagination strategy for APIs (OFFSET/LIMIT vs keyset)
  • Selecting index types for query patterns (B-tree, GIN, hash, covering)
  • Checking for common anti-patterns before deploying queries

Best practices

  • List explicit columns instead of SELECT * to reduce I/O and prevent unexpected schema changes
  • Prefer range filters (date >= ...) over functions on columns to allow index use
  • Use NOT EXISTS instead of NOT IN when NULLs may be present
  • Favor keyset pagination for large offsets; use OFFSET/LIMIT only for small, simple pages
  • Create covering indexes for frequent SELECT columns to avoid table lookups

Example use cases

  • Generate an active user list, then join aggregated order counts via chained CTEs
  • Compute running totals and previous-period comparisons using LAG/ROW_NUMBER/SUM OVER
  • Paginate product lists in an API using keyset pagination for high-offset performance
  • Choose a GIN index for JSONB array searches and a B-tree for ORDER BY and range filters
  • Replace N+1 queries by joining or batching related rows in a single query

FAQ

When should I use a CTE versus a subquery?

Use CTEs for clarity, reuse, and complex multi-step logic. For single-use, simple subqueries can be marginally faster in some engines, but clarity often favors CTEs.

How do I pick between OFFSET/LIMIT and keyset pagination?

Use OFFSET/LIMIT for small offsets and simple UIs. Use keyset (seek) pagination for large datasets or high-offset pages to avoid increasing cost as offset grows.

Which index type should I choose for JSONB searches?

Use a GIN index for JSONB containment and array searches. B-tree is better for range queries and ORDER BY on scalar columns.