> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getparable.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Basic queries

# Basic Check-ins Queries

This guide provides simple, ready-to-use SQL queries for Planning Center Check-ins data. Each query is designed to answer common ministry questions without requiring deep SQL knowledge.

<Card title="Query Customization Required" icon="circle-exclamation" color="#FFA500" horizontal>
  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.
</Card>

## Query Requirements

### Schema Prefix

**IMPORTANT:** All tables in the Planning Center Check-ins module live in the `planning_center` schema. Always prefix table names with `planning_center.` when writing queries.

✅ CORRECT: `SELECT * FROM planning_center.checkins_checkins`
❌ INCORRECT: `SELECT * FROM checkins_checkins`

### Row Level Security (RLS)

Row Level Security automatically enforces:

* **tenant\_organization\_id** – results limited to your organization
* **system\_status** – only active records returned by default

**Skip manual filters for these columns**—RLS already applies them and redundant predicates can slow queries or mask data:

* ❌ `WHERE tenant_organization_id = 1`
* ❌ `WHERE system_status = 'active'`

Focus your WHERE clauses on ministry-specific logic while trusting the database to keep tenant and status filters in place.

## Today's Attendance

### Who Checked In Today?

```sql theme={null}
-- List everyone who checked in today
SELECT
    first_name,
    last_name,
    kind as check_in_type,
    security_code,
    created_at as checked_in_at,
    CASE
        WHEN checked_out_at IS NULL THEN 'Still here'
        ELSE 'Checked out'
    END as status
FROM planning_center.checkins_checkins
WHERE DATE(created_at) = CURRENT_DATE
ORDER BY created_at DESC;
```

### Count Total Attendance by Type

```sql theme={null}
-- See how many regulars, guests, and volunteers checked in today
SELECT
    kind as attendee_type,
    COUNT(*) as total
FROM planning_center.checkins_checkins
WHERE DATE(created_at) = CURRENT_DATE
GROUP BY kind
ORDER BY total DESC;
```

### Currently Checked In (Not Yet Checked Out)

```sql theme={null}
-- Find who is still checked in right now
SELECT
    first_name,
    last_name,
    security_code,
    kind as type,
    created_at as checked_in_at,
    EXTRACT(HOUR FROM AGE(NOW(), created_at)) as hours_checked_in
FROM planning_center.checkins_checkins
WHERE DATE(created_at) = CURRENT_DATE
  AND checked_out_at IS NULL
ORDER BY created_at;
```

## Location-Based Queries

### Check-ins by Location

```sql theme={null}
-- Count check-ins for each location today
SELECT
    l.name as location_name,
    COUNT(c.check_in_id) as total_checkins
FROM planning_center.checkins_locations l
LEFT JOIN planning_center.checkins_checkin_relationships cr
    ON l.location_id = cr.relationship_id
    AND cr.relationship_type = 'Location'
LEFT JOIN planning_center.checkins_checkins c
    ON cr.checkin_id = c.check_in_id
    AND DATE(c.created_at) = CURRENT_DATE
GROUP BY l.name
HAVING COUNT(c.check_in_id) > 0
ORDER BY total_checkins DESC;
```

### Room Capacity Status

```sql theme={null}
-- Check how full each room is
SELECT
    l.name as room,
    l.max_occupancy as capacity,
    COUNT(c.check_in_id) as current_count,
    CASE
        WHEN l.max_occupancy IS NULL THEN 'No limit set'
        WHEN COUNT(c.check_in_id) >= l.max_occupancy THEN 'FULL'
        WHEN COUNT(c.check_in_id) >= l.max_occupancy * 0.8 THEN 'Nearly full'
        ELSE 'Space available'
    END as status
FROM planning_center.checkins_locations l
LEFT JOIN planning_center.checkins_checkin_relationships cr
    ON l.location_id = cr.relationship_id
    AND cr.relationship_type = 'Location'
LEFT JOIN planning_center.checkins_checkins c
    ON cr.checkin_id = c.check_in_id
    AND DATE(c.created_at) = CURRENT_DATE
    AND c.checked_out_at IS NULL  -- Only currently present
WHERE l.kind = 'Folder'  -- Physical locations only
GROUP BY l.name, l.max_occupancy
ORDER BY l.name;
```

## Guest Tracking

### First-Time Guests This Week

```sql theme={null}
-- Find all first-time guests from the past 7 days
SELECT
    first_name,
    last_name,
    DATE(created_at) as visit_date,
    security_code
FROM planning_center.checkins_checkins
WHERE one_time_guest = true
  AND created_at >= CURRENT_DATE - INTERVAL '7 days'
ORDER BY created_at DESC;
```

### Guest vs Regular Comparison

```sql theme={null}
-- Compare guest and regular attendance by day this month
SELECT
    DATE(created_at) as date,
    COUNT(CASE WHEN kind = 'Guest' THEN 1 END) as guests,
    COUNT(CASE WHEN kind = 'Regular' THEN 1 END) as regulars,
    COUNT(*) as total
FROM planning_center.checkins_checkins
WHERE created_at >= DATE_TRUNC('month', CURRENT_DATE)
GROUP BY DATE(created_at)
ORDER BY date DESC;
```

## Volunteer Management

### Today's Volunteers

```sql theme={null}
-- List all volunteers who checked in today
SELECT
    first_name,
    last_name,
    created_at as checked_in_at,
    CASE
        WHEN checked_out_at IS NULL THEN 'Currently serving'
        ELSE 'Finished serving'
    END as status
FROM planning_center.checkins_checkins
WHERE kind = 'Volunteer'
  AND DATE(created_at) = CURRENT_DATE
ORDER BY created_at;
```

### Volunteer Coverage by Hour

```sql theme={null}
-- See volunteer coverage throughout the day
SELECT
    DATE_TRUNC('hour', created_at) as hour,
    COUNT(*) as volunteers_checked_in
FROM planning_center.checkins_checkins
WHERE kind = 'Volunteer'
  AND DATE(created_at) = CURRENT_DATE
GROUP BY DATE_TRUNC('hour', created_at)
ORDER BY hour;
```

## Weekly Patterns

### Attendance by Day of Week (Last 30 Days)

```sql theme={null}
-- See which days have the highest attendance
SELECT
    TO_CHAR(created_at, 'Day') as day_of_week,
    COUNT(*) as total_checkins,
    COUNT(DISTINCT DATE(created_at)) as number_of_days,
    ROUND(COUNT(*)::NUMERIC / COUNT(DISTINCT DATE(created_at))) as avg_per_day
FROM planning_center.checkins_checkins
WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY TO_CHAR(created_at, 'Day'), EXTRACT(DOW FROM created_at)
ORDER BY EXTRACT(DOW FROM created_at);
```

### Peak Check-in Times

```sql theme={null}
-- Find when most people check in
SELECT
    TO_CHAR(created_at, 'HH:00 AM') as hour,
    COUNT(*) as checkins
FROM planning_center.checkins_checkins
WHERE created_at >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY TO_CHAR(created_at, 'HH:00 AM'), EXTRACT(HOUR FROM created_at)
ORDER BY EXTRACT(HOUR FROM created_at);
```

## Event Analysis

### Recent Events with Attendance

```sql theme={null}
-- Show events and their attendance counts
SELECT
    e.name as event_name,
    COUNT(DISTINCT c.check_in_id) as total_attendance
FROM planning_center.checkins_events e
LEFT JOIN planning_center.checkins_checkin_relationships cr
    ON e.event_id = cr.relationship_id
    AND cr.relationship_type = 'Event'
LEFT JOIN planning_center.checkins_checkins c
    ON cr.checkin_id = c.check_in_id
    AND c.created_at >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY e.name
HAVING COUNT(DISTINCT c.check_in_id) > 0
ORDER BY total_attendance DESC;
```

### Event Frequency Settings

```sql theme={null}
-- See how often events are scheduled
SELECT
    name as event,
    frequency,
    CASE
        WHEN archived_at IS NOT NULL THEN 'Archived'
        ELSE 'Active'
    END as status
FROM planning_center.checkins_events
ORDER BY name;
```

## Security and Safety

### Security Codes in Use Today

```sql theme={null}
-- List all security codes currently in use
SELECT DISTINCT
    security_code,
    COUNT(*) as times_used
FROM planning_center.checkins_checkins
WHERE DATE(created_at) = CURRENT_DATE
  AND checked_out_at IS NULL
  AND security_code IS NOT NULL
GROUP BY security_code
ORDER BY security_code;
```

### Emergency Contact Information

```sql theme={null}
-- Find check-ins with emergency contacts
SELECT
    first_name,
    last_name,
    emergency_contact_name,
    emergency_contact_phone_number,
    security_code,
    created_at
FROM planning_center.checkins_checkins
WHERE DATE(created_at) = CURRENT_DATE
  AND emergency_contact_name IS NOT NULL
ORDER BY created_at DESC;
```

## Medical and Special Needs

### Check-ins with Medical Notes

```sql theme={null}
-- Find children with medical notes
SELECT
    first_name,
    last_name,
    medical_notes,
    security_code,
    created_at as checked_in_at
FROM planning_center.checkins_checkins
WHERE medical_notes IS NOT NULL
  AND medical_notes != ''
  AND DATE(created_at) = CURRENT_DATE
ORDER BY created_at DESC;
```

## Time-Based Analysis

### Average Check-in Duration

```sql theme={null}
-- Calculate how long people typically stay
SELECT
    kind as attendee_type,
    COUNT(*) as total_checkouts,
    ROUND(AVG(EXTRACT(EPOCH FROM (checked_out_at - created_at))/3600), 1) as avg_hours
FROM planning_center.checkins_checkins
WHERE checked_out_at IS NOT NULL
  AND created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY kind
ORDER BY avg_hours DESC;
```

### Busiest Check-in Days (Last 3 Months)

```sql theme={null}
-- Find the days with the most check-ins
SELECT
    DATE(created_at) as date,
    TO_CHAR(created_at, 'Day') as day_name,
    COUNT(*) as total_checkins
FROM planning_center.checkins_checkins
WHERE created_at >= CURRENT_DATE - INTERVAL '3 months'
GROUP BY DATE(created_at), TO_CHAR(created_at, 'Day')
ORDER BY total_checkins DESC
LIMIT 10;
```

## Tips for Using These Queries

1. **Dates**: Replace `CURRENT_DATE` with specific dates like `'2024-01-07'` to query historical data
2. **Limits**: Add `LIMIT 10` to any query to see just the first 10 results
3. **Sorting**: Change `DESC` to `ASC` if you want to reverse the sort order
4. **Filtering**: Add more `WHERE` conditions to narrow your results

## Next Steps

Ready for more complex analysis? Check out:

* [Advanced Queries](/planning-center/check-ins/advanced-queries) - Multi-table joins and complex calculations
* [Reporting Examples](/planning-center/check-ins/reporting-examples) - Complete reports ready for leadership
* [Data Model](/planning-center/check-ins/data-model) - Understand all available fields and relationships
