Clinical trial: sites, patients, visits and adverse events

Two trials across nine sites: enrolment, scheduled visits, dosing, lab biomarkers and graded adverse events, all in the right order.

Two clinical trials across nine sites: 314 patients randomised to treatment or placebo, their scheduled visits, dose administrations with reductions that stay, lab biomarkers with reference ranges, and adverse events graded by CTCAE. Dates run in the order a monitor would expect.

  • clinical trials
  • pharma
  • CDISC-style
  • adverse events
  • biostatistics
0150300Jan 2025Apr 2025Jul 2025Oct 2025Jan 2026Apr 2026Jul 2026Aug 2026
Rows per month in treatment_visits.scheduled_date, counted from the file.

Explore

Every table, profiled

Each column's type, spread, empties and most common values, measured from the CSVs in the download. Switch to the first rows to see the data exactly as it sits in the file.

lab_biomarkers.csv

15,404 rows · 9 columns · 2 foreign keys

lab_idprimary key
unique on every row
15,404 distinctno empties
visit_idforeign key
points to treatment_visits.visit_id
2,968 distinctno empties
patient_idforeign key
points to patients.patient_id
314 distinctno empties
analytecategory
  • ALT
    19%
  • Creatinine
    19%
  • Platelet count
    19%
  • White blood cell count
    19%
  • Hemoglobin
    19%
  • 1 more value · 6.6%
6 valuesno empties
unitcategory
  • 10^3/uL
    37%
  • mg/dL
    25%
  • U/L
    19%
  • g/dL
    19%
4 valuesno empties
measured_valuenumber
0.4log scale343.9
mean 60.45median 13.90 to 460.4no empties
reference_range_lownumber
0.6log scale150
mean 37.04median 70.6 to 150no empties
reference_range_highnumber
1.3log scale400
mean 97.34median 17.51.3 to 400no empties
is_out_of_rangeyes / no
true · 10%false · 90%
no empties

Keys

Every join resolves

13 foreign keys, 48,778 references checked against the table each one points at. None points at a row that does not exist.

adverse_events

  • patient_idpatients.patient_id0 orphans
  • visit_idtreatment_visits.visit_id0 orphans
  • trial_idtrials.trial_id0 orphans

dose_administrations

  • visit_idtreatment_visits.visit_id0 orphans
  • patient_idpatients.patient_id0 orphans

lab_biomarkers

  • visit_idtreatment_visits.visit_id0 orphans
  • patient_idpatients.patient_id0 orphans

patients

  • site_idsites.site_id0 orphans
  • trial_idtrials.trial_id0 orphans

sites

  • trial_idtrials.trial_id0 orphans

treatment_visits

  • patient_idpatients.patient_id0 orphans
  • trial_idtrials.trial_id0 orphans
  • site_idsites.site_id0 orphans

Checks

What we checked

  • 13 foreign-key relationships checked, 0 orphaned rows
  • No row is dated before the row it belongs to
  • 314 patients in 2 arms (treatment 158, control_placebo 156)
  • 716 adverse events graded by CTCAE, 5.9% serious, and 100% have an onset on or after the patient's enrolment
  • 10.3% of 15,404 lab values fall outside their reference range, and the flag agrees with the range in 100% of rows
  • 96.3% of 3,083 scheduled visits were completed, and 100% of completed visits fall on or after enrolment
  • Dose reductions stay: 45% of treatment-arm patients stepped down at least once and 0 doses went back up; 0 doses are dated before their patient's enrolment

The same checks ship in the zip as INTEGRITY.txt, so you can rerun them in any SQL engine. How we verify

Questions, answered

Worth asking it

Each answer is the query's result on these exact files. Open one for its SQL and rows, then check your own query against it.

  1. 1Is the adverse event rate different between the treatment and placebo arms?control_placebo: 1.4 events per patient, 77.6% with any; treatment: 3.15 events per patient, 94.3% with any.
    with ae as (
      select patient_id, count(*) as events,
             sum(case when serious then 1 else 0 end) as serious,
             sum(case when ctc_grade >= 3 then 1 else 0 end) as grade_3_plus
      from adverse_events
      group by patient_id
    )
    select p.arm,
           count(*) as patients,
           round(100.0 * sum(case when ae.events > 0 then 1 else 0 end) / count(*), 1) as with_any_ae_pct,
           round(1.0 * sum(coalesce(ae.events, 0)) / count(*), 2) as events_per_patient,
           sum(coalesce(ae.serious, 0)) as serious_events,
           sum(coalesce(ae.grade_3_plus, 0)) as grade_3_plus_events
    from patients p
    left join ae on ae.patient_id = p.patient_id
    group by p.arm
    order by p.arm
    armpatientswith_any_ae_pctevents_per_patientserious_eventsgrade_3_plus_events
    control_placebo15677.61.41225
    treatment15894.33.153071
  2. 2Which biomarkers drift out of range after dosing?The largest rise after the first visit: Hemoglobin in treatment, 4.1% to 15.8% out of range.
    -- Out-of-range share at the first visit against every later visit, by arm.
    select l.analyte, p.arm,
           round(100.0 * sum(case when v.visit_number = 1 and l.is_out_of_range then 1 else 0 end)
                 / nullif(sum(case when v.visit_number = 1 then 1 else 0 end), 0), 1) as first_visit_out_pct,
           round(100.0 * sum(case when v.visit_number > 1 and l.is_out_of_range then 1 else 0 end)
                 / nullif(sum(case when v.visit_number > 1 then 1 else 0 end), 0), 1) as later_visits_out_pct
    from lab_biomarkers l
    join treatment_visits v on v.visit_id = l.visit_id
    join patients p on p.patient_id = l.patient_id
    group by l.analyte, p.arm
    order by l.analyte, p.arm
    analytearmfirst_visit_out_pctlater_visits_out_pct
    ALTcontrol_placebo66.1
    ALTtreatment5.35.8
    Creatininecontrol_placebo6.75.8
    Creatininetreatment7.48.2
    Glucosecontrol_placebo4958
    Glucosetreatment53.758.1
    Hemoglobincontrol_placebo4.85.2
    Hemoglobintreatment4.115.8
    Platelet countcontrol_placebo4.15.3
    Platelet counttreatment26.1
    White blood cell countcontrol_placebo6.85.5
    White blood cell counttreatment10.19.2
  3. 3What share of patients withdraw or are lost, and when?active 44.9%; completed 40.1%; withdrawn 9.9% after a median 124 days; lost_to_followup 5.1% after a median 225 days.
    select status,
           count(*) as patients,
           round(100.0 * count(*) / (select count(*) from patients), 1) as share_pct,
           round(percentile_cont(0.5) within group (order by extract(epoch from (coalesce(withdrawn_at, lost_at) - enrolled_at)) / 86400), 0)
             as median_days_from_enrolment
    from patients
    group by status
    order by patients desc
    statuspatientsshare_pctmedian_days_from_enrolment
    active14144.9
    completed12640.1
    withdrawn319.9124
    lost_to_followup165.1225
  4. 4How does visit completion vary by site?Completion runs from 94.0% at Munich Cancer Institute to 98.3% at Boston University Hospital.
    select s.site_name, s.city, s.country,
           count(*) as scheduled_visits,
           round(100.0 * sum(case when v.visit_completed then 1 else 0 end) / count(*), 1) as completed_pct
    from treatment_visits v
    join sites s on s.site_id = v.site_id
    group by s.site_id, s.site_name, s.city, s.country
    order by completed_pct
    site_namecitycountryscheduled_visitscompleted_pct
    Munich Cancer InstituteBengaluruIndia21894
    Madrid Community HospitalChicagoUnited States22594.7
    Boston Memorial HospitalBristolUnited Kingdom35194.9
    Boston University HospitalRio de JaneiroBrazil22195.9
    Paris Regional Medical CenterAmsterdamNetherlands44796
    Toronto Regional Medical CenterNew YorkUnited States10197
    Toronto Cancer InstituteAmsterdamNetherlands1,07097.1
    Toronto Memorial HospitalChicagoUnited States39197.4
    Boston University HospitalAustinUnited States5998.3

Every query runs on the files in the download as they are. ANSWERS.sql holds all of them; run it in DuckDB from the dataset's folder.

Use it

Take it, or make one shaped like yours

Rebuild it byte for byte

The zip includes RECIPE.json: the Studio pack, the overrides and seed 20260921 that made these exact rows.

Your own tables, your own numbers

Describe the data you need in Studio and get connected tables with the totals you state, profiled like this and checked before you download.

Premium datasets

All premium
  • Card spending each month, debit and credit

    2,500 US households at five banks and seven card issuers, two years

    Five banks' raw statement lines, with every label behind them

    Answer key

    • description
    • merchant_name
    • category
    • +6 more
    Rows
    7,627,186
    Tables
    14
    Checks
    50 of 50
    Free previewProfile and preview
  • transactions, rows per monthMay 2025 – Oct 2026

    One UAE bank, 10,000 customers, eighteen months

    A UAE bank's whole trail from KYC to STR, with the laundering nobody caught

    Answer key

    • is_suspicious
    • typology
    • ring_id
    • +7 more
    Rows
    11,711,393
    Tables
    16
    Checks
    129 of 129
    Free previewProfile and preview
  • Weekly sales, at regular price and on promotion

    Grocery chain, 10 stores, fiscal 2024 and 2025

    Two fiscal years of a grocery chain, from the shelf to the receipt

    Answer key

    • baseline_units
    • price_effect
    • promo_lift
    • +7 more
    Rows
    2,790,852
    Tables
    14
    Checks
    117 of 117
    Free preview18-question projectProfile and preview

Related free datasets

All 12

Fully synthetic. No real person, company or transaction is represented, and no production data was read to make it. CC0: use it anywhere, no attribution needed.