Real-World SQL Applications
SQL knowledge earns its value when applied to actual business problems. This page walks through how SQL is used in practice — not toy examples, but the kinds of queries that run in production data warehouses, BI dashboards, and ETL pipelines every day.
1. Sales Analytics Dashboard
Most BI tools (Tableau, Looker, Metabase) execute SQL under the hood. Understanding the queries they generate — and being able to write them yourself — is what separates analysts from report consumers.
Monthly revenue trend:
SELECT DATE_TRUNC('month', order_date) AS month, COUNT(*) AS order_count, COUNT(DISTINCT customer_id) AS unique_customers, SUM(amount) AS revenue, ROUND(SUM(amount) / COUNT(DISTINCT customer_id), 2) AS revenue_per_customerFROM ordersWHERE order_date >= DATE_TRUNC('year', CURRENT_DATE) AND status = 'completed'GROUP BY 1ORDER BY 1;Revenue by category with month-over-month growth:
WITH monthly_revenue AS ( SELECT DATE_TRUNC('month', o.order_date) AS month, p.category, SUM(oi.quantity * oi.unit_price) AS revenue FROM orders o JOIN order_items oi ON o.order_id = oi.order_id JOIN products p ON oi.product_id = p.product_id WHERE o.status = 'completed' GROUP BY 1, 2)SELECT month, category, revenue, LAG(revenue) OVER (PARTITION BY category ORDER BY month) AS prev_month_revenue, ROUND( 100.0 * (revenue - LAG(revenue) OVER (PARTITION BY category ORDER BY month)) / NULLIF(LAG(revenue) OVER (PARTITION BY category ORDER BY month), 0), 1 ) AS mom_growth_pctFROM monthly_revenueORDER BY month DESC, revenue DESC;2. Customer Cohort Analysis
Cohort analysis answers: do customers who joined in different time periods behave differently? It’s a foundational retention analysis.
-- Month 0: how much did each acquisition cohort spend in their first month?-- Month 1: how much did they spend in month 2? And so on.WITH cohorts AS ( SELECT customer_id, DATE_TRUNC('month', MIN(order_date)) AS cohort_month FROM orders GROUP BY customer_id),cohort_orders AS ( SELECT c.cohort_month, DATE_TRUNC('month', o.order_date) AS order_month, COUNT(DISTINCT o.customer_id) AS active_customers, SUM(o.amount) AS revenue FROM cohorts c JOIN orders o ON c.customer_id = o.customer_id GROUP BY 1, 2)SELECT cohort_month, order_month, EXTRACT(MONTH FROM AGE(order_month, cohort_month)) AS months_since_acquisition, active_customers, revenueFROM cohort_ordersORDER BY cohort_month, months_since_acquisition;3. ETL / Data Pipeline Queries
SQL is used heavily in ELT pipelines (especially with dbt) to transform raw data into analytics-ready tables.
Deduplicating raw event data:
-- Keep the most recent version of each record (CDC dedup pattern)WITH ranked AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY order_id ORDER BY updated_at DESC ) AS rn FROM raw_orders)SELECT order_id, customer_id, status, amount, created_at, updated_atFROM rankedWHERE rn = 1;SCD Type 2: tracking historical changes:
-- Find records that changed between yesterday's snapshot and today'sSELECT t.customer_id, t.email AS new_email, y.email AS old_email, t.updated_atFROM customers_today tJOIN customers_yesterday y ON t.customer_id = y.customer_idWHERE t.email != y.email OR t.status != y.status;Incremental load pattern:
-- Only process records newer than the last successful loadINSERT INTO analytics.ordersSELECT *FROM raw.ordersWHERE created_at > ( SELECT COALESCE(MAX(created_at), '1900-01-01') FROM analytics.orders)ON CONFLICT (order_id) DO UPDATE SET status = EXCLUDED.status, updated_at = EXCLUDED.updated_at;4. Fraud Detection
Pattern-based fraud detection runs as SQL queries against transaction data:
-- Flag accounts with unusual transaction velocityWITH recent_txns AS ( SELECT account_id, COUNT(*) AS txn_count_24h, SUM(amount) AS total_amount_24h, COUNT(DISTINCT merchant_id) AS unique_merchants_24h FROM transactions WHERE created_at >= NOW() - INTERVAL '24 hours' GROUP BY account_id)SELECT r.account_id, r.txn_count_24h, r.total_amount_24h, a.average_daily_txns, r.txn_count_24h / NULLIF(a.average_daily_txns, 0) AS velocity_ratioFROM recent_txns rJOIN account_baselines a ON r.account_id = a.account_idWHERE r.txn_count_24h > a.average_daily_txns * 5 -- 5x normal velocity OR r.total_amount_24h > a.typical_daily_spend * 10;5. Inventory Management
Products at or below reorder threshold:
SELECT p.product_id, p.name, p.sku, i.quantity_on_hand, p.reorder_point, p.reorder_quantity, s.name AS primary_supplierFROM products pJOIN inventory i ON p.product_id = i.product_idJOIN suppliers s ON p.primary_supplier_id = s.supplier_idWHERE i.quantity_on_hand <= p.reorder_point AND p.is_active = TRUEORDER BY (i.quantity_on_hand::float / NULLIF(p.reorder_point, 0)) ASC;Inventory turnover by product:
SELECT p.product_id, p.name, SUM(oi.quantity) AS units_sold_90d, AVG(i.quantity_on_hand) AS avg_stock, ROUND(SUM(oi.quantity) / NULLIF(AVG(i.quantity_on_hand), 0), 2) AS turnover_ratioFROM products pJOIN order_items oi ON p.product_id = oi.product_idJOIN orders o ON oi.order_id = o.order_idJOIN inventory i ON p.product_id = i.product_idWHERE o.order_date >= CURRENT_DATE - 90GROUP BY p.product_id, p.nameORDER BY turnover_ratio DESC;6. User Activity and Funnel Analysis
Conversion funnel: signup → first action → purchase:
SELECT COUNT(DISTINCT u.user_id) AS signups, COUNT(DISTINCT a.user_id) AS activated, COUNT(DISTINCT p.customer_id) AS purchased, ROUND(100.0 * COUNT(DISTINCT a.user_id) / COUNT(DISTINCT u.user_id), 1) AS activation_rate, ROUND(100.0 * COUNT(DISTINCT p.customer_id) / COUNT(DISTINCT a.user_id), 1) AS purchase_rateFROM users uLEFT JOIN ( SELECT DISTINCT user_id FROM events WHERE event_type = 'first_action') a ON u.user_id = a.user_idLEFT JOIN ( SELECT DISTINCT customer_id FROM orders WHERE status = 'completed') p ON u.user_id = p.customer_idWHERE u.created_at >= '2025-01-01';Day-N retention (users who returned N days after signup):
WITH day_one AS ( SELECT user_id, DATE(created_at) AS signup_date FROM users),activity AS ( SELECT DISTINCT user_id, DATE(event_at) AS active_date FROM events)SELECT d.signup_date, COUNT(DISTINCT d.user_id) AS new_users, COUNT(DISTINCT CASE WHEN a.active_date = d.signup_date + 1 THEN a.user_id END) AS day_1_retained, COUNT(DISTINCT CASE WHEN a.active_date = d.signup_date + 7 THEN a.user_id END) AS day_7_retainedFROM day_one dLEFT JOIN activity a ON d.user_id = a.user_idGROUP BY 1ORDER BY 1 DESC;7. Reporting Queries with ROLLUP
When stakeholders want category subtotals and a grand total on the same report:
SELECT COALESCE(region, 'TOTAL') AS region, COALESCE(category, 'ALL') AS category, SUM(revenue) AS total_revenue, COUNT(DISTINCT customer_id) AS customersFROM salesGROUP BY ROLLUP (region, category)ORDER BY region NULLS LAST, category NULLS LAST;The result includes rows for each (region, category) combination, subtotals per region, and a single grand total row.