← back to Professional Directory
docs/example-queries.sql
170 lines
-- Professional Directory — example queries
-- Run after Stage 1 (NPI ingestion). Each query honors opted_out = false.
-- ─── 1. Where are doctors setting up private practice? ──────────────────────
-- Top LA County ZIPs by physician count.
SELECT
z.zip,
z.city,
COUNT(DISTINCT p.id) AS physicians,
COUNT(DISTINCT o.id) AS orgs,
COUNT(DISTINCT p.id) + COUNT(DISTINCT o.id) AS total_entities
FROM la_zips z
LEFT JOIN organizations o
ON o.zip = z.zip AND o.opted_out = false
LEFT JOIN professional_locations pl
ON pl.address ILIKE '%' || z.zip || '%'
LEFT JOIN professionals p
ON p.id = pl.professional_id AND p.opted_out = false
GROUP BY z.zip, z.city
ORDER BY total_entities DESC
LIMIT 30;
-- ─── 2. Beverly Hills only ──────────────────────────────────────────────────
-- 90210 / 90211 / 90212 — all "Beverly Hills" in la_zips.
SELECT
o.zip,
COUNT(DISTINCT o.id) AS orgs,
COUNT(DISTINCT pl.professional_id) AS distinct_doctors,
STRING_AGG(DISTINCT s.name, ', ' ORDER BY s.name) AS specialties_present
FROM organizations o
LEFT JOIN professional_locations pl ON pl.organization_id = o.id
LEFT JOIN professionals p ON p.id = pl.professional_id
LEFT JOIN professional_specialties ps ON ps.professional_id = p.id
LEFT JOIN specialties s ON s.id = ps.specialty_id
WHERE o.zip IN ('90210','90211','90212')
AND o.opted_out = false
GROUP BY o.zip
ORDER BY o.zip;
-- ─── 3. Specialty heat map by city ──────────────────────────────────────────
-- Where do dermatologists, cardiologists, plastic surgeons concentrate?
SELECT
o.city,
COUNT(*) FILTER (WHERE s.name ILIKE '%Dermatolog%') AS dermatology,
COUNT(*) FILTER (WHERE s.name ILIKE '%Cardio%') AS cardiology,
COUNT(*) FILTER (WHERE s.name ILIKE '%Plastic%') AS plastic_surgery,
COUNT(*) FILTER (WHERE s.name ILIKE '%Pediatric%') AS pediatrics,
COUNT(*) FILTER (WHERE s.name ILIKE '%Psych%') AS psychiatry
FROM organizations o
LEFT JOIN professional_locations pl ON pl.organization_id = o.id
LEFT JOIN professional_specialties ps ON ps.professional_id = pl.professional_id
LEFT JOIN specialties s ON s.id = ps.specialty_id
WHERE o.opted_out = false
GROUP BY o.city
ORDER BY dermatology + cardiology + plastic_surgery DESC
LIMIT 20;
-- ─── 4. Solo practice vs group practice mix per city ───────────────────────
SELECT
o.city,
COUNT(*) FILTER (WHERE o.type = 'private_practice') AS solo_practices,
COUNT(*) FILTER (WHERE o.type = 'medical_group') AS groups,
COUNT(*) FILTER (WHERE o.type = 'hospital') AS hospitals,
COUNT(*) FILTER (WHERE o.type = 'urgent_care') AS urgent_cares,
COUNT(*) FILTER (WHERE o.type = 'surgery_center') AS surgery_centers
FROM organizations o
WHERE o.opted_out = false AND o.county = 'Los Angeles'
GROUP BY o.city
ORDER BY solo_practices + groups DESC
LIMIT 30;
-- ─── 5. "Find me a top-confidence cardiologist in 90210" ────────────────────
SELECT
p.full_name,
p.npi_number,
p.license_number,
p.license_status,
pl.address,
pl.phone,
o.name AS practice_name,
o.website,
p.source_confidence_score
FROM professionals p
JOIN professional_specialties ps ON ps.professional_id = p.id
JOIN specialties s ON s.id = ps.specialty_id
JOIN professional_locations pl ON pl.professional_id = p.id
LEFT JOIN organizations o ON o.id = pl.organization_id
WHERE p.opted_out = false
AND s.name ILIKE '%Cardio%'
AND (pl.address ILIKE '%90210%' OR o.zip IN ('90210','90211','90212'))
AND p.source_confidence_score >= 0.85
ORDER BY p.source_confidence_score DESC, p.last_name;
-- ─── 6. SEO landing page: "Best dermatologists in West Hollywood" ──────────
SELECT
p.full_name,
p.medical_school,
p.graduation_year,
pl.address,
pl.phone,
o.website,
p.profile_image_url,
p.bio
FROM professionals p
JOIN professional_specialties ps ON ps.professional_id = p.id
JOIN specialties s ON s.id = ps.specialty_id
JOIN professional_locations pl ON pl.professional_id = p.id
LEFT JOIN organizations o ON o.id = pl.organization_id
WHERE p.opted_out = false
AND s.name ILIKE '%Dermatolog%'
AND (pl.address ILIKE '%West Hollywood%' OR o.city = 'West Hollywood')
AND p.license_status = 'Active'
ORDER BY p.source_confidence_score DESC NULLS LAST
LIMIT 25;
-- ─── 7. "Where are the hospitals, by ZIP density?" ─────────────────────────
SELECT
o.zip,
z.city,
COUNT(*) AS hospitals,
STRING_AGG(o.name, ' | ' ORDER BY o.name) AS hospital_names
FROM organizations o
LEFT JOIN la_zips z ON z.zip = o.zip
WHERE o.type = 'hospital' AND o.opted_out = false
GROUP BY o.zip, z.city
ORDER BY hospitals DESC, o.zip;
-- ─── 8. Doctors per capita proxy: practices per ZIP ────────────────────────
-- Rough density indicator. Pair with US Census ACS population data later.
SELECT
o.zip,
COUNT(*) AS practices,
COUNT(DISTINCT pl.professional_id) AS distinct_doctors,
ROUND(
COUNT(DISTINCT pl.professional_id)::NUMERIC
/ NULLIF(COUNT(*),0)::NUMERIC, 2
) AS doctors_per_practice
FROM organizations o
LEFT JOIN professional_locations pl ON pl.organization_id = o.id
WHERE o.opted_out = false AND o.zip IS NOT NULL
GROUP BY o.zip
HAVING COUNT(*) >= 5
ORDER BY practices DESC
LIMIT 50;
-- ─── 9. Recently licensed ──────────────────────────────────────────────────
-- Doctors enumerated in the past 3 years (NPI enumeration_date proxy).
SELECT
EXTRACT(YEAR FROM p.license_issue_date) AS year_started,
o.city,
COUNT(*) AS new_doctors
FROM professionals p
LEFT JOIN professional_locations pl ON pl.professional_id = p.id
LEFT JOIN organizations o ON o.id = pl.organization_id
WHERE p.license_issue_date >= NOW() - INTERVAL '3 years'
AND p.opted_out = false
GROUP BY year_started, o.city
ORDER BY year_started DESC, new_doctors DESC;
-- ─── 10. Provenance audit — which sources did we pull each fact from? ─────
SELECT
s.source_name,
rr.entity_type,
COUNT(*) AS records,
MAX(rr.fetched_at) AS most_recent
FROM raw_records rr
JOIN sources s ON s.id = rr.source_id
GROUP BY s.source_name, rr.entity_type
ORDER BY s.source_name, rr.entity_type;