Start here to learn the fundamentals of querying your church’s giving data. Each example builds on the previous one, helping you gain confidence with SQL.
Query Customization Required
These example queries demonstrate common patterns but may require adjustments to match your specific database schema and field names. Test thoroughly in your environment before use.
IMPORTANT: All tables in the Planning Center Giving module live in the planning_center schema. Always prefix table names with planning_center. in your queries.✅ CORRECT: SELECT * FROM planning_center.giving_donations
❌ INCORRECT: SELECT * FROM giving_donations
-- View the 20 most recent donationsSELECT donation_id, amount_cents / 100.0 as amount, -- Convert cents to dollars amount_currency, payment_method, received_at, refunded -- true if this donation was refundedFROM planning_center.giving_donationsWHERE received_at IS NOT NULL -- Only completed donationsORDER BY received_at DESCLIMIT 20;
-- Find all donations over $500SELECT donation_id, amount_cents / 100.0 as amount, payment_method, received_atFROM planning_center.giving_donationsWHERE amount_cents >= 50000 -- $500 in cents AND received_at IS NOT NULL AND refunded = false -- Exclude refunded donationsORDER BY amount_cents DESC;
-- Find donors by nameSELECT person_id, first_name, last_name, donor_numberFROM planning_center.giving_peopleWHERE LOWER(last_name) LIKE '%smith%' -- Case-insensitive search OR LOWER(first_name) LIKE '%john%'ORDER BY last_name, first_name;
This query shows how to link donations with donor information using the relationship table:
-- See donations with donor namesSELECT d.donation_id, d.amount_cents / 100.0 as amount, d.received_at, p.first_name, p.last_name, p.donor_numberFROM planning_center.giving_donations d-- Join through the relationship tableJOIN planning_center.giving_donation_relationships dr ON d.donation_id = dr.donation_id AND dr.relationship_type = 'Person' -- Specify we want the Person relationship-- Join to the people tableJOIN planning_center.giving_people p ON dr.relationship_id = p.person_idWHERE d.received_at >= CURRENT_DATE - INTERVAL '30 days' -- Last 30 daysORDER BY d.received_at DESCLIMIT 50;
-- See all your church's fundsSELECT fund_id, name, description, is_default, -- true for your general/default fund visibility -- 'everywhere', 'admin_only', etc.FROM planning_center.giving_fundsWHERE visibility = 'everywhere' -- Only publicly visible fundsORDER BY name;
-- View designations (how donations are allocated to funds)SELECT des.designation_id, des.amount_cents / 100.0 as amount, f.name as fund_name, f.description as fund_descriptionFROM planning_center.giving_designations desJOIN planning_center.giving_funds f ON des.fund_id = f.fund_idORDER BY des.amount_cents DESCLIMIT 100;
-- See how each donation was designated to fundsSELECT d.donation_id, d.amount_cents / 100.0 as total_donation, des.amount_cents / 100.0 as designated_amount, f.name as fund_nameFROM planning_center.giving_donations d-- Join to designation relationshipsJOIN planning_center.giving_designation_relationships desr ON d.donation_id = desr.designation_id AND desr.relationship_type = 'Donation'-- Join to designationsJOIN planning_center.giving_designations des ON desr.relationship_id = des.designation_id-- Join to fundsJOIN planning_center.giving_funds f ON des.fund_id = f.fund_idWHERE d.received_at >= CURRENT_DATE - INTERVAL '7 days'ORDER BY d.received_at DESC;
-- All donations received this monthSELECT COUNT(*) as donation_count, SUM(amount_cents) / 100.0 as total_amountFROM planning_center.giving_donationsWHERE received_at >= DATE_TRUNC('month', CURRENT_DATE) AND received_at < DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '1 month' AND refunded = false;
-- Weekly giving for the last 8 weeksSELECT DATE_TRUNC('week', received_at) as week_starting, COUNT(*) as donation_count, SUM(amount_cents) / 100.0 as total_amount, AVG(amount_cents) / 100.0 as average_donationFROM planning_center.giving_donationsWHERE received_at >= CURRENT_DATE - INTERVAL '8 weeks' AND refunded = falseGROUP BY DATE_TRUNC('week', received_at)ORDER BY week_starting DESC;
-- Total giving for the current yearSELECT COUNT(DISTINCT donation_id) as total_donations, SUM(amount_cents) / 100.0 as total_given, AVG(amount_cents) / 100.0 as average_donation, MAX(amount_cents) / 100.0 as largest_donationFROM planning_center.giving_donationsWHERE received_at >= DATE_TRUNC('year', CURRENT_DATE) AND received_at < DATE_TRUNC('year', CURRENT_DATE) + INTERVAL '1 year' AND refunded = false;
-- See how people prefer to giveSELECT payment_method, COUNT(*) as donation_count, SUM(amount_cents) / 100.0 as total_amount, AVG(amount_cents) / 100.0 as average_amountFROM planning_center.giving_donationsWHERE received_at >= CURRENT_DATE - INTERVAL '90 days' AND refunded = falseGROUP BY payment_methodORDER BY total_amount DESC;
-- Compare electronic vs check donationsSELECT CASE WHEN payment_method = 'check' THEN 'Check' WHEN payment_method IN ('card', 'ach', 'paypal') THEN 'Electronic' ELSE 'Other' END as payment_type, COUNT(*) as donation_count, SUM(amount_cents) / 100.0 as total_amountFROM planning_center.giving_donationsWHERE received_at >= CURRENT_DATE - INTERVAL '30 days' AND refunded = falseGROUP BY payment_typeORDER BY total_amount DESC;
-- Daily totals for the last 14 daysSELECT DATE(received_at) as donation_date, COUNT(*) as num_donations, COUNT(DISTINCT dr.relationship_id) as unique_donors, SUM(d.amount_cents) / 100.0 as total_amount, MIN(d.amount_cents) / 100.0 as smallest_donation, MAX(d.amount_cents) / 100.0 as largest_donationFROM planning_center.giving_donations dLEFT JOIN planning_center.giving_donation_relationships dr ON d.donation_id = dr.donation_id AND dr.relationship_type = 'Person'WHERE d.received_at >= CURRENT_DATE - INTERVAL '14 days' AND d.refunded = falseGROUP BY DATE(d.received_at)ORDER BY donation_date DESC;
-- Top 10 giving amounts this month (no names for privacy)SELECT dr.relationship_id as donor_id, -- Anonymous ID COUNT(*) as donation_count, SUM(d.amount_cents) / 100.0 as total_givenFROM planning_center.giving_donations dJOIN planning_center.giving_donation_relationships dr ON d.donation_id = dr.donation_id AND dr.relationship_type = 'Person'WHERE d.received_at >= DATE_TRUNC('month', CURRENT_DATE) AND d.refunded = falseGROUP BY dr.relationship_idORDER BY total_given DESCLIMIT 10;
-- How much has been given to each fund this yearSELECT f.name as fund_name, COUNT(DISTINCT des.designation_id) as num_designations, SUM(des.amount_cents) / 100.0 as total_designatedFROM planning_center.giving_designations desJOIN planning_center.giving_funds f ON des.fund_id = f.fund_id-- Get the donation date through relationshipsJOIN planning_center.giving_designation_relationships desr ON des.designation_id = desr.designation_id AND desr.relationship_type = 'Donation'JOIN planning_center.giving_donations d ON desr.relationship_id = d.donation_idWHERE d.received_at >= DATE_TRUNC('year', CURRENT_DATE) AND d.refunded = falseGROUP BY f.fund_id, f.nameORDER BY total_designated DESC;