Analytical SQL for Business Intelligence
Write BI-grade SQL for cohort analysis, funnels, YoY growth, Pareto analysis, and executive KPIs.
๐ฏ What You'll Learn
- Cohort analysis for customer retention tracking
- Funnel analysis for conversion optimization
- Year-over-year growth, percentiles, and Pareto analysis
- ROLLUP dashboards with drill-down and moving annual totals
- KPI queries: LTV, MRR, churn rate
๐ Cohort Analysis
Cohort analysis groups users by when they first appeared and tracks how they behave over time. It answers: "Are we retaining customers better this month than last month?" โ the most important question for any subscription business.
Cohort Retention Analysis
Track customer retention by signup month
-- COHORT ANALYSIS: group users by signup month, track retention
WITH cohorts AS (
SELECT customer_id,
DATE_TRUNC('month', first_order_date) AS cohort_month
FROM (
SELECT customer_id, MIN(order_date) AS first_order_date
FROM orders GROUP BY customer_id
) first_orders
),
monthly_activity AS (
SELECT o.customer_id,
c.cohort_month,
DATE_TRUNC('month', o.order_date) AS activity_month,
EXTRACT(MONTH FROM AGE(
...๐ป Funnel Analysis
Funnel analysis measures drop-off at each step of a user journey โ from page view โ add to cart โ checkout โ purchase. Finding the biggest drop-off tells you where to focus optimization efforts.
๐ก Pro Tip โ NULLIF for Safe Division
Always wrap denominators in NULLIF(value, 0) to avoid division-by-zero errors. 100 / NULLIF(0, 0) returns NULL instead of crashing.
Funnel Analysis
Conversion rates across the purchase journey
-- FUNNEL ANALYSIS: track conversion through stages
WITH funnel AS (
SELECT
session_id,
MAX(CASE WHEN event = 'page_view' THEN 1 ELSE 0 END) AS viewed,
MAX(CASE WHEN event = 'add_to_cart' THEN 1 ELSE 0 END) AS added,
MAX(CASE WHEN event = 'checkout_start' THEN 1 ELSE 0 END) AS checkout,
MAX(CASE WHEN event = 'purchase' THEN 1 ELSE 0 END) AS purchased
FROM events
WHERE event_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY session_id
)
SE
...๐ Window Functions for BI
Window functions are the backbone of analytical SQL โ year-over-year comparisons, percentile distributions, and Pareto (80/20) analysis.
BI Window Functions
YoY growth, percentiles, and Pareto analysis
-- BI-GRADE WINDOW FUNCTIONS
-- Year-over-Year comparison:
SELECT
DATE_TRUNC('month', order_date) AS month,
SUM(total) AS revenue,
LAG(SUM(total), 12) OVER (ORDER BY DATE_TRUNC('month', order_date))
AS revenue_last_year,
ROUND(
(SUM(total) - LAG(SUM(total), 12) OVER (
ORDER BY DATE_TRUNC('month', order_date)
)) / NULLIF(LAG(SUM(total), 12) OVER (
ORDER BY DATE_TRUNC('month', order_date)
), 0) * 100, 1
) AS yoy_growth_pc
...๐ง Dashboard ROLLUPs
ROLLUP creates hierarchical subtotals perfect for drill-down dashboards. Combined with moving annual totals, it powers the executive view of business performance.
Dashboard ROLLUPs
Drill-down reports and moving annual totals
-- ROLLUP for BI dashboards
-- Sales dashboard with drill-down levels:
SELECT
COALESCE(region, '๐ GLOBAL') AS region,
COALESCE(category, '๐ฆ ALL CATEGORIES') AS category,
COALESCE(TO_CHAR(DATE_TRUNC('quarter', sale_date), 'YYYY-"Q"Q'),
'๐
ALL TIME') AS quarter,
SUM(revenue) AS total_revenue,
COUNT(DISTINCT customer_id) AS unique_customers,
ROUND(SUM(revenue) / NULLIF(COUNT(DISTINCT customer_id), 0), 2)
AS revenue_per_customer,
COUNT(*) AS trans
...๐ฏ Executive KPIs
Customer Lifetime Value, Monthly Recurring Revenue, and Churn Rate โ the three metrics every executive dashboard needs. Pure SQL, no BI tool required.
โ ๏ธ Common Mistake
Calculating churn rate as churned/total instead of churned/total-at-start-of-period. The denominator should be the customer count at the beginning of the period, not the end.
Executive KPIs
LTV, MRR, and churn rate queries
-- KPI QUERIES for executive dashboards
-- Customer Lifetime Value (LTV):
SELECT
ROUND(AVG(lifetime_value), 2) AS avg_ltv,
ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (
ORDER BY lifetime_value
), 2) AS median_ltv
FROM (
SELECT customer_id, SUM(total) AS lifetime_value
FROM orders
GROUP BY customer_id
) customer_ltv;
-- Monthly Recurring Revenue (MRR):
SELECT DATE_TRUNC('month', billing_date) AS month,
SUM(CASE WHEN type = 'new' THEN amount END) AS new_mrr,
S
...๐ Quick Reference
| Analysis | Key SQL Feature |
|---|---|
| Cohort retention | CTE + FIRST_VALUE window |
| Funnel conversion | CASE WHEN + SUM |
| YoY growth | LAG(value, 12) |
| Percentiles | PERCENTILE_CONT |
| Pareto 80/20 | Cumulative SUM window |
๐ Lesson Complete!
You can now write BI-grade analytical SQL for any executive dashboard. Next, learn about query profiling across database engines!
Sign up for free to track which lessons you've completed and get learning reminders.