Role-Based Guides

WhoDB for Data Analysts

WhoDB for Data Analysts

As a data analyst, you need a powerful tool that bridges the gap between raw databases and actionable insights. WhoDB provides everything you need: interactive filtering, advanced SQL capabilities, complex query execution, and flexible data export—all without leaving your browser.

Analytics Workflow Overview

The typical analytics workflow in WhoDB follows four phases: explore, analyze, validate, and export.

Explore Data

Understand table structure, identify relevant data, apply initial filters

Analyze & Query

Write complex SQL, aggregate data, find patterns and trends

Validate Results

Verify queries, cross-check results, ensure data accuracy

Export & Share

Export in multiple formats, prepare for stakeholders and dashboards

Phase 1: Data Exploration

Before writing complex queries, understand what data you're working with.

Interactive Table Exploration

Understanding Relationships

Navigate to related tables to understand your data model:

Phase 2: Complex Analysis Queries

Once you understand your data, write sophisticated queries to extract insights.

Opening the Query Interface

Essential Analytics Queries

Aggregation & Summarization

Group data to find patterns and trends:

sql

-- Sales by product category (most common analytics pattern)
SELECT
  category,
  COUNT(*) as transaction_count,
  SUM(amount) as total_revenue,
  AVG(amount) as avg_transaction_size,
  MAX(amount) as max_transaction,
  MIN(amount) as min_transaction,
  STDDEV(amount) as revenue_volatility
FROM orders
WHERE created_at >= '2024-01-01'
  AND status = 'completed'
GROUP BY category
ORDER BY total_revenue DESC;

Time Series Analysis

Track metrics over time to identify trends:

sql

-- Monthly revenue trend with growth rate
WITH monthly_sales AS (
  SELECT
    DATE_TRUNC('month', created_at)::date as month,
    SUM(amount) as revenue,
    COUNT(*) as transaction_count
  FROM orders
  WHERE status = 'completed'
    AND created_at >= '2023-01-01'
  GROUP BY DATE_TRUNC('month', created_at)
)
SELECT
  month,
  revenue,
  transaction_count,
  LAG(revenue) OVER (ORDER BY month) as previous_month_revenue,
  ROUND(((revenue - LAG(revenue) OVER (ORDER BY month)) /
         LAG(revenue) OVER (ORDER BY month) * 100)::numeric, 2) as growth_percent
FROM monthly_sales
ORDER BY month DESC;

This reveals whether your metrics are growing, stable, or declining.

Cohort Analysis

Track how different user groups behave over time:

sql

-- User retention by signup cohort
WITH user_cohorts AS (
  SELECT
    user_id,
    DATE_TRUNC('month', created_at)::date as signup_month
  FROM users
),
user_activity AS (
  SELECT DISTINCT
    user_id,
    DATE_TRUNC('month', activity_date)::date as activity_month
  FROM user_events
  WHERE event_type = 'purchase'
)
SELECT
  c.signup_month,
  EXTRACT(YEAR FROM AGE(a.activity_month, c.signup_month)) * 12 +
  EXTRACT(MONTH FROM AGE(a.activity_month, c.signup_month)) as months_since_signup,
  COUNT(DISTINCT c.user_id) as active_users
FROM user_cohorts c
LEFT JOIN user_activity a ON c.user_id = a.user_id
GROUP BY c.signup_month, months_since_signup
ORDER BY c.signup_month DESC, months_since_signup;

This shows which signup cohorts have the best retention and engagement.

Join-Based Analysis

Combine data from multiple tables:

sql

-- Customer lifetime value analysis
SELECT
  c.customer_id,
  c.customer_name,
  c.segment,
  COUNT(o.order_id) as lifetime_orders,
  SUM(o.amount) as lifetime_value,
  AVG(o.amount) as avg_order_value,
  MAX(o.created_at) as last_purchase_date,
  MIN(o.created_at) as first_purchase_date,
  DATEDIFF(MAX(o.created_at), MIN(o.created_at)) as customer_tenure_days
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.customer_name, c.segment
ORDER BY lifetime_value DESC;

This powerful pattern combines customer attributes with their transaction history.

Window Functions for Context

Calculate metrics while preserving row-level detail:

sql

-- Orders ranked by amount, with percentile context
SELECT
  order_id,
  customer_id,
  amount,
  ROW_NUMBER() OVER (ORDER BY amount DESC) as rank,
  PERCENT_RANK() OVER (ORDER BY amount) * 100 as percentile,
  SUM(amount) OVER (ORDER BY amount DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as running_total
FROM orders
WHERE created_at >= '2024-01-01'
ORDER BY amount DESC
LIMIT 100;

Window functions let you see individual records alongside aggregate context.

Anomaly Detection

Find unusual values that deviate from normal patterns:

sql

-- Detect transactions that are statistical outliers
WITH transaction_stats AS (
  SELECT
    AVG(amount) as avg_amount,
    STDDEV(amount) as std_dev
  FROM orders
  WHERE created_at >= NOW() - INTERVAL '90 days'
)
SELECT
  o.order_id,
  o.customer_id,
  o.amount,
  ts.avg_amount,
  ROUND((o.amount - ts.avg_amount) / ts.std_dev, 2) as std_deviations_from_mean,
  CASE
    WHEN ABS(o.amount - ts.avg_amount) > (3 * ts.std_dev) THEN 'ANOMALY'
    WHEN ABS(o.amount - ts.avg_amount) > (2 * ts.std_dev) THEN 'UNUSUAL'
    ELSE 'NORMAL'
  END as classification
FROM orders o, transaction_stats ts
WHERE ABS(o.amount - ts.avg_amount) > (2 * ts.std_dev)
ORDER BY ABS(o.amount - ts.avg_amount) DESC;

This finds outliers that might indicate fraud, data errors, or significant business events.

Query Execution & Results

Multi-Cell Queries

For complex analysis, break your work into multiple cells:

Phase 3: Data Validation

Before sharing analysis results, validate your queries.

Validation Checklist

Phase 4: Exporting & Sharing

Once validated, export your analysis results.

Export Workflow

Real-World Analytics Scenarios

Scenario 1: Customer Segmentation

Identify different customer groups for targeted marketing:

sql

-- Segment customers by behavior
SELECT
  c.customer_id,
  c.customer_name,
  c.segment_category,
  COUNT(o.order_id) as lifetime_orders,
  SUM(o.amount) as lifetime_value,
  MAX(o.created_at) as last_purchase,
  DATEDIFF(NOW(), MAX(o.created_at)) as days_since_purchase,
  CASE
    WHEN SUM(o.amount) > 5000 AND DATEDIFF(NOW(), MAX(o.created_at)) < 30 THEN 'High Value Active'
    WHEN SUM(o.amount) > 5000 AND DATEDIFF(NOW(), MAX(o.created_at)) < 90 THEN 'High Value At Risk'
    WHEN SUM(o.amount) > 1000 AND DATEDIFF(NOW(), MAX(o.created_at)) < 30 THEN 'Medium Value Active'
    WHEN SUM(o.amount) <= 1000 AND COUNT(o.order_id) >= 5 THEN 'Small Value Loyal'
    WHEN COUNT(o.order_id) = 1 THEN 'One-Time Buyer'
    ELSE 'Dormant'
  END as customer_segment
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.customer_name, c.segment_category
ORDER BY lifetime_value DESC;

Export this for marketing teams to enable targeted campaigns.

Scenario 2: Churn Prediction

Identify customers at risk of leaving:

sql

-- Find customers showing churn signals
WITH customer_activity AS (
  SELECT
    c.customer_id,
    c.customer_name,
    COUNT(o.order_id) as total_orders,
    MAX(o.created_at) as last_order_date,
    DATEDIFF(NOW(), MAX(o.created_at)) as days_inactive,
    AVG(o.amount) as avg_order_value,
    STDDEV(o.amount) as order_volatility
  FROM customers c
  LEFT JOIN orders o ON c.customer_id = o.customer_id
  GROUP BY c.customer_id, c.customer_name
)
SELECT
  *,
  CASE
    WHEN days_inactive > 180 AND total_orders < 5 THEN 'HIGH RISK'
    WHEN days_inactive > 90 AND total_orders < 10 THEN 'MEDIUM RISK'
    WHEN days_inactive > 60 THEN 'LOW RISK'
    ELSE 'STABLE'
  END as churn_risk
FROM customer_activity
WHERE days_inactive > 60
ORDER BY days_inactive DESC;

Scenario 3: Product Performance Analysis

Identify your best and worst performing products:

sql

-- Detailed product performance metrics
SELECT
  p.product_id,
  p.product_name,
  p.category,
  COUNT(DISTINCT oi.order_id) as times_sold,
  SUM(oi.quantity) as total_units_sold,
  SUM(oi.quantity * oi.price) as total_revenue,
  AVG(oi.price) as avg_price,
  MIN(oi.price) as min_price,
  MAX(oi.price) as max_price,
  ROUND(SUM(oi.quantity * oi.price) / NULLIF(COUNT(DISTINCT oi.order_id), 0), 2) as revenue_per_sale,
  ROW_NUMBER() OVER (PARTITION BY p.category ORDER BY SUM(oi.quantity * oi.price) DESC) as rank_in_category
FROM products p
LEFT JOIN order_items oi ON p.product_id = oi.product_id
GROUP BY p.product_id, p.product_name, p.category
ORDER BY total_revenue DESC;

Performance Optimization for Large Datasets

Query Optimization

Troubleshooting Query Issues

Best Practices for Analytics

Start with Questions

Begin with a specific business question, not just exploration. This focuses your analysis.

Validate Your Data

Cross-check results different ways. Verify row counts and value ranges.

Document Assumptions

When exporting, document date ranges, filters applied, and what NULLs mean.

Use Read-Only Access

When possible, connect to read-only replicas to avoid accidental data modification.

Use Query History

Reuse queries from Scratchpad history, and store important query files in your normal documentation or repository.

Iterate Incrementally

Build complex queries step-by-step. Test each piece before adding more complexity.

Next Steps

Continue mastering WhoDB analytics:

Database Exploration

Learn how to explore and understand new datasets

Advanced Queries

Master complex SQL patterns and optimization

Data Export

Learn export customization for different audiences

Where Conditions

Master filtering techniques for focused analysis