Export Explorer: Query Library
This document contains a collection of SQL queries that can be used with the Export Explorer. Unless otherwise noted, the SQL provided below can be directly pasted as-is for the most complete results or it can be further narrowed/specified by implementing changes noted as modifications.
Many of the queries in this article require you to specify one participant by their participantidentifier
. If there are multiple participants that you'd like included in the output, you can change participantidentifer = '#'
to participantidentifier in ('#1', '#2')
, replacing #1 and #2 with the participant identifiers you want. You can keep adding additional participants with a comma and single quotes.
These queries are also available directly in Export Explorer by clicking on the "Library" button in the Queries menu. Select any query to create a new tab containing that query, make any modifications needed, and run the query.

Analytic Events
Email Events
Description: As written, the SQL below will list the count of all email-related events during the entire duration of the project for all participants. Based on the Analytics Events Export.
SQL: Email Events
SELECT
type,
COUNT(*) AS number
FROM
analyticsevents ae
WHERE
ae.type LIKE 'Email%' --change to '%' to see all notifications
-- AND participantidentifier = 'MDH-1234' -- change to a participant identifier of interest
-- AND ae.timestamp BETWEEN DATE '2024-03-01' AND DATE '2024-06-01' -- set the dates of interest
GROUP BY
Type
Modifications:
- Change
'Email%'
to'%'
to show all analytics events. - Change
'Email%'
to'Sms%'
to show SMS events instead of email events. - Change Like
'Email%'
toin (['EventType1',….])
and replace['EventType1',…]
with a list of event types (e.g.,in ('SmsFailure', 'SmsOptout')
). - Remove
--
before-- AND participantidentifier = 'MDH-1234'
and replace'MDH-1234'
with an identifier of interest to only show for this identifier. - Remove
--
before-- AND ae.timestamp BETWEEN DATE '2024-03-01' AND DATE '2024-06-01'
and change the dates to the dates of interest to only show events for a specific time frame.
Sample Output:

Email Events by Month
Description: As written, the SQL below will list the count of all email-related events during the entire duration of the project for all participants by month and year. Based on the Analytics Events Export.
SQL: Email Events by Month
SELECT
TYPE,
CONCAT(
CAST(YEAR(timestamp) AS VARCHAR),
'-',
DATE_FORMAT(timestamp, '%M')
) AS year_month,
COUNT(*) AS number
FROM
analyticsevents ae
WHERE
ae.type LIKE 'Email%' --change to '%' to see all notifications
-- AND participantidentifier = 'MDH-1234' -- change to a participant identifier of interest
-- AND ae.timestamp BETWEEN DATE '2024-03-01' AND DATE '2024-06-01' -- set the dates
GROUP BY
TYPE,
YEAR(timestamp),
DATE_FORMAT(timestamp, '%M')
ORDER BY
TYPE,
YEAR(timestamp),
MIN(timestamp)
Modifications:
- Change
'Email%'
to‘%’
to show all analytics events. - Change
'Email%'
to'Sms%'
to show SMS events instead of email events. - Change Like
'Email%'
toin (['EventType1',….]) and replace ['EventType1',…]
with a list of event types (e.g.,in ('SmsFailure', 'SmsOptout')
). - Remove
--
before-- AND participantidentifier = 'MDH-1234' and replace 'MDH-1234'
with an identifier of interest to only show for this identifier. - Remove
--
before-- AND ae.timestamp BETWEEN DATE '2024-03-01' AND DATE '2024-06-01'
and change the dates to the dates of interest to only show events for a specific time frame.
Sample Output:

Bounced Email Addresses
Description: As written, the SQL below will list all email addresses that have bounced during the duration of the project. Based on the Analytics Events Export.
SQL: Bounced Email Addresses
SELECT
participantidentifier,
timestamp,
element_at(PROPERTIES, 'MailDestination') AS bounced_email,
element_at(PROPERTIES, 'BounceType') AS bounce_Type
FROM
analyticsevents ae
WHERE
TYPE = 'EmailBounce'
-- AND ae.participantidentifier = 'MDH-1234' -- change to a participant identifier of interest
--AND ae.timestamp BETWEEN DATE '2024-03-01' AND DATE '2024-06-01' -- set the dates
ORDER BY
timestamp DESC
Modifications:
- Remove
--
before-- AND participantidentifier = 'MDH-1234' and replace 'MDH-1234'
with an identifier of interest to only show for this identifier. - Remove
--
before-- AND ae.timestamp BETWEEN DATE '2024-03-01' AND DATE '2024-06-01'
and change the dates to the dates of interest to only show events for a specific time frame. - Remove
--
before-- AND ae.timestamp BETWEEN DATE '2024-03-01' AND DATE '2024-06-01'
and change toAND ae.timestamp > '2024-09-01'
to show only bounced email addresses after a certain date.
Sample Output:

Surveys & Survey Tasks
Readable Survey Results
Description: As written, the SQL below will list all survey results in a tabular format that can be downloaded as a CSV for easy review in tools such as Microsoft Excel. This includes both the questions and answers for each survey step. Based on the Survey Results Export.
SQL: Readable Survey Results
SELECT
sqr.participantidentifier,
sr.surveyname,
sr.surveyversion,
ssr.stepidentifier,
sqr.resultidentifier,
sd.questiontext,
sd.answerformat,
sd.answerchoices,
sqr.answers,
sqr.startdate,
sqr.enddate
FROM
surveyquestionresults sqr
JOIN surveystepresults ssr ON ssr.surveystepresultkey = sqr.surveystepresultkey
JOIN surveyresults sr ON sr.surveyresultkey = sqr.surveyresultkey
LEFT JOIN surveydictionary sd ON sd.surveykey = sr.surveykey
AND sd.surveyversion = sr.surveyversion
AND sd.stepidentifier = ssr.stepidentifier
AND sd.resultidentifier = sqr.resultidentifier
-- where sqr.startdate BETWEEN DATE '2024-02-01' AND DATE '2024-02-28'
-- where sr.surveyname=''
-- where sqr.participantidentifier='MDH-1234'
ORDER BY
sqr.startdate DESC,
sqr.participantidentifier ASC,
sr.surveyname ASC
Modifications:
- Remove
--
before-- where sqr.startdate BETWEEN DATE '2024-02-01' AND DATE '2024-02-28'
and change the dates to the dates of interest to only show results for a specific time frame. - Remove
--
before-- where sr.surveyname=''
and insert the name of a survey between''
to list results only for that survey. - If you wish to use multiple criteria, then only keep the first where and change the remaining
where
toAND
.
Sample Output:

Participant Details
Custom Field Changes
Description: As written, the SQL below will list the various values of a custom field though time that have been performed by a coordinator for a specific participant. Based on the Participant Data Export.
The SQL below must be modified for it to work for the custom fields in your project.
SQL: Custom Field Changes
SELECT
participantidentifier,
USER,
TRIM([CustomFieldName]) [CustomFieldName],
MIN(timestamp) AS change_date
FROM
(
SELECT
timestamp,
PROPERTIES ['User'] AS USER,
participantidentifier,
CAST(
json_extract_scalar(
PROPERTIES ['Change'],
'$.CustomFields.[CustomFieldName]'
) AS varchar
) AS CompletedDate
FROM
analyticsevents
WHERE
TYPE = 'ParticipantUpdated'
AND PROPERTIES ['UserType'] = 'Coordinator'
) x
WHERE
participantidentifier = 'MDH-1234' -- update participant identifier here
AND CompletedDate IS NOT NULL
GROUP BY
participantidentifier,
USER,
TRIM([CustomFieldName])
ORDER BY
participantidentifier,
MIN(timestamp) DESC
Required Modifications:
Each of the following must be updated for this to work in your project:
- Replace all four instance of
[CustomFieldName]
with the name of your customfield (e.g.,TRIM([CustomFieldName]) [CustomFieldName]
, would becomeTRIM(MyCustomField)
MyCustomField. - Replace
MDH-1234
in one instance ofparticipant identifier = 'MDH-1234'
with the participant identifier of interest.
Sample Output:

Device Data
Apple Health (HealthKit) Samples
Description: As written, the SQL will show sample counts, first sample date, and most recent sample date for each sample type for all participants for all time. Based on the Apple HealthKitV2 Samples Export.
SQL: Apple Health (HealthKit) Samples
SELECT
devicemodel,
TYPE,
count(DISTINCT healthkitsamplekey) Samples,
max(DATE) most_recent,
min(DATE) oldest
FROM
healthkitv2samples
WHERE
devicemodel IS NOT NULL
--and participantidentifier ='MDH-1234'
--and date BETWEEN DATE '2023-01-01' AND DATE '2024-09-28'
GROUP BY
devicemodel,
TYPE
ORDER BY
devicemodel DESC
Modifications:
- Remove
--
before-- and participantidentifier ='MDH-1234'
and change the identifier to your indentifier of interest to look at a specific participant. - Remove
--
before--and date BETWEEN DATE '2023-01-01' AND DATE '2024-09-28'
and change the dates to the dates of interest to only show results for a specific time frame.
Sample Output:

Activities
Description: As written, the SQL will show activity counts for all participants for all time across garmin, applehealth, and fitbit workouts. Based on the Apple HealthKitV2 Workouts Export, Fitbit Activity Log Export, and Garmin Activity Summary Export.
SQL: Activities
SELECT
Source,
activitytype,
count(*) AS number
FROM
(
SELECT
'Garmin' Source,
Upper(activitytype) activitytype,
participantidentifier
FROM
garminactivitysummary
UNION
SELECT
'FitBit' Source,
UPPER(activityname) activitytype,
participantidentifier
FROM
fitbitactivitylogs
UNION
SELECT
'Healthkit' Source,
Upper(activitytype) activitytype,
participantidentifier
FROM
healthkitv2workouts
) x
--WHERE x.participantidentifier = 'MDH-1234'
--where source='Garmin'
GROUP BY
Source,
activitytype
ORDER BY
Activitytype
Modifications:
- Remove
--
beforeWHERE x.participantidentifier = 'MDH-1234'
and change the identifier to your identifier of interest to look at a specific participant. - Remove
--
before--where source='Garmin'
and update the source to Garmin, FitBit, or Healthkit. (capitlization matters). - Remove
UNION SELECT 'Healthkit' Source, Upper(activitytype) activitytype, participantidentifier FROM healthkitv2workouts
if your project is not configured to collect Workout data from Apple Health.
Sample Output:

Electronic Health Record Data
Medical Record Connections
Description: As written, the SQL will show the participant counts, most recent connection, and oldest connection for all Provider and External Health Plan (participant mediated) connections across all time. Based on the External Accounts Data Export.
SQL: Medical Record Connections
SELECT
fhr.providername,
ea.providercategory,
count(DISTINCT fhr.participantidentifier) participants,
max(ea.connectiondate) most_recent,
min(ea.connectiondate) oldest
FROM
"fhirbulkparticipantidentifiersmapping" fhr
LEFT OUTER JOIN externalaccounts ea ON ea.providername = fhr.providername
WHERE
providercategory IN ('Provider', 'Health Plan')
-- and fhr.participantidentifier='MDH-1234'
GROUP BY
fhr.providername,
ea.providercategory
ORDER BY
count(DISTINCT fhr.participantidentifier) DESC
Modifications:
- Remove
--
before-- and fhr.participantidentifier='MDH-1234'
and replaceMDH-1234
with the identifier of interest.
Sample Output:

FHIR Resources
Description: As written, the SQL will show the count of participants with each diagnosis obtained from either claims or provider electronic health records across all time and sorted from most common to least common. Based on the EHR Export.
SQL: FHIR Resources
SELECT
resourcetype,
code,
display,
count(DISTINCT participantidentifier) AS participants
FROM
(
SELECT
fb.resourcetype,
coding_item['code'] AS code,
coding_item['display'] AS display,
coding_item['userSelected'] AS userSelected,
MAP.participantidentifier
FROM
fhirbulk fb
JOIN fhirbulkparticipantidentifiersmapping MAP ON MAP.fhirpatientid = fb.fhirpatientid
CROSS JOIN UNNEST (
CAST(
json_extract(resource, '$.code.coding') AS ARRAY < MAP < varchar,
varchar > >
)
) AS t (coding_item)
WHERE
resourcetype IN ('Condition') -- ‘Condition’=Diagnosis, 'Observation'=labs and vitals 'Procedure'=procedures
) x
WHERE
userSelected = 'false'
GROUP BY
resourcetype,
code,
display
ORDER BY
count(DISTINCT participantidentifier) DESC
Modifications:
- Choose one or multiple resources by updating
IN ('Condition')
to have one or multiple items from‘Condition’=Diagnosis, 'Observation'=labs and vitals 'Procedure'=procedures
(e.g.,IN (‘Condition’, ‘Procedure’)
).
Sample Output:

Segments
Segment History
Description: As written, the SQL will show the history of all segments that a given participant has been in, including the date they were added and the date they were removed. Based on the Segment Participant History Data Export.
SQL: Segment History
SELECT
sph.participantidentifier,
sph.segmentname,
sph.adddate,
sph.removedate
FROM
segmentparticipanthistory sph
WHERE
sph.participantidentifier = 'MDH-1234'
--and sph.segmentname='Device (most recent)'
Modifications:
- Update
sph.participantidentifier = 'MDH-1234'
to include your identifier of interest to look at a specific participant. - Remove
--
before-- and sph.segmentname='Device (most recent)'
and replace thesegmentname
with the segment name of interest.
Sample Output:

All Current Segments
Description: As written, the SQL will show the all of the segments that a given participant is currently on including, the date they were added. Based on the Segment Participants Data Export.
SQL: All Current Segments
SELECT
sp.participantidentifier,
sp. segmentname,
sp.adddate
FROM
segmentparticipants sp
WHERE
sp.participantidentifier = 'MDH-1234'
--and sph.segmentname='Device (most recent)'
Modifications:
- Update
sp.participantidentifier = 'MDH-1234'
to include your identifier of interest to look at a specific participant. - Remove
--
before-- and sph.segmentname='Device (most recent)'
and replace thesegmentname
with the segment name of interest.
Sample Output:
