Query order
Written order versus the order the database runs it.
SQL
SELECT -- 5. choose columns
FROM -- 1. pick tables
JOIN -- 2. combine
WHERE -- 3. filter rows
GROUP BY -- 4. group
HAVING -- 6. filter groups
ORDER BY -- 7. sort
LIMIT -- 8. cutFiltering
SQL
WHERE amount BETWEEN 10 AND 100
AND region IN ('North', 'West')
AND name LIKE 'A%' -- starts with A
AND email IS NOT NULL
AND NOT (status = 'test')Aggregation
SQL
SELECT region,
COUNT(*) AS rows,
COUNT(DISTINCT customer) AS customers,
SUM(amount) AS revenue,
AVG(amount) AS avg_order
FROM orders
GROUP BY region
HAVING SUM(amount) > 1000;Joins
SQL
FROM orders o
JOIN customers c ON c.id = o.customer_id -- matches only
LEFT JOIN refunds r ON r.order_id = o.id -- keep all orders
FULL OUTER JOIN x ON ... -- keep both sides
CROSS JOIN dim_date d -- every combinationAnti join
Rows with no match. Safer than NOT IN.
SQL
SELECT c.*
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id
);CTEs
SQL
WITH monthly AS (
SELECT DATE_TRUNC('month', order_date) AS m,
SUM(amount) AS revenue
FROM orders GROUP BY 1
)
SELECT * FROM monthly WHERE revenue > 5000;Ranking
SQL
ROW_NUMBER() OVER (PARTITION BY customer_id
ORDER BY order_date DESC)
RANK() OVER (ORDER BY revenue DESC)
DENSE_RANK() OVER (ORDER BY revenue DESC)
NTILE(4) OVER (ORDER BY revenue) -- quartilesRunning totals and change
SQL
SUM(amount) OVER (ORDER BY d
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
AVG(amount) OVER (ORDER BY d
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW)
LAG(revenue) OVER (ORDER BY month)
LEAD(revenue) OVER (ORDER BY month)CASE
SQL
CASE
WHEN amount >= 1000 THEN 'Large'
WHEN amount >= 100 THEN 'Medium'
ELSE 'Small'
END AS order_sizeNULL handling
SQL
COALESCE(discount, 0) -- first non-null
NULLIF(orders, 0) -- 0 becomes NULL
amount / NULLIF(qty, 0) -- safe divide
WHERE col IS NULL -- never = NULLDates (dialects vary)
SQL
CURRENT_DATE
DATE_TRUNC('month', order_date)
EXTRACT(YEAR FROM order_date)
order_date + INTERVAL '7 days' -- PostgreSQL
DATEADD(day, 7, order_date) -- Snowflake
DATEDIFF('day', start_d, end_d) -- SnowflakeSet operations
SQL
SELECT id FROM a
UNION ALL -- keep duplicates, fastest
SELECT id FROM b;
UNION -- remove duplicates
INTERSECT -- in both
EXCEPT -- in first, not secondCreate and change
SQL
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE
);
INSERT INTO customers (id, name) VALUES (1, 'Ana');
UPDATE customers SET name = 'Anna' WHERE id = 1;
DELETE FROM customers WHERE id = 1;Find duplicates
SQL
SELECT email, COUNT(*) AS n
FROM customers
GROUP BY email
HAVING COUNT(*) > 1;Written by Alessandro Ecclesie Agazzi, freelance analytics engineer in London. Updated 30 September 2026.