Templates & Examples

Start with a template and customize for your business. Replace date ranges and filters to fit your needs.

Daily Gross Volume

SELECT
  date_trunc('day', created_at) AS day,
  sum(amount) AS gross_amount
FROM analytics.payments
WHERE status = 'succeeded'
  AND created_at >= :start AND created_at < :end
GROUP BY 1
ORDER BY 1;

Payment Method Mix

SELECT
  payment_method_type,
  sum(amount) AS gross_amount
FROM analytics.payments
WHERE status = 'succeeded'
  AND created_at >= :start AND created_at < :end
GROUP BY 1
ORDER BY gross_amount DESC;

Refund Rate (Last 30 Days)

WITH charges AS (
  SELECT count(*) AS cnt
  FROM analytics.payments
  WHERE status = 'succeeded'
    AND created_at >= now() - interval '30 days'
),
refunds AS (
  SELECT count(*) AS cnt
  FROM analytics.refunds
  WHERE created_at >= now() - interval '30 days'
)
SELECT refunds.cnt::decimal / nullif(charges.cnt, 0) AS refund_rate;

Payout Reconciliation Summary

SELECT
  p.id AS payout_id,
  p.arrival_date,
  sum(bt.net) AS net_total,
  sum(bt.fee) AS fee_total
FROM analytics.payouts p
JOIN analytics.balance_transactions bt
  ON bt.source_id = p.id
WHERE p.arrival_date >= :start AND p.arrival_date < :end
GROUP BY 1, 2
ORDER BY 2 DESC;

Top Customers by Lifetime Value

SELECT
  c.id,
  coalesce(c.email, '(no email)') AS email,
  sum(p.amount) AS lifetime_value
FROM analytics.customers c
JOIN analytics.payments p
  ON p.customer_id = c.id
WHERE p.status = 'succeeded'
GROUP BY 1, 2
ORDER BY lifetime_value DESC
LIMIT 50;

Tips

  • Use parameters like :start and :end to reuse queries easily.
  • Add LIMIT during exploration; remove or adjust for full runs.
  • Consider aggregating before exporting for faster downloads.

Last updated: 2025-10-20


What’s Next