HIPAA-Safe Clarity SQL

HIPAA-Safe Clarity SQL: How to Query Epic Data Without Exposing PHI

HIPAA-safe Clarity SQL means every query returns only the data its purpose requires. You run it from an authorized source, and the output limits re-identification. Most privacy incidents in analytics do not come from attackers. They come from a well-meaning analyst who exports patient-level rows to Excel for a quick check.

I have supported UAT and reporting teams on Epic projects where that export happened. The fix is a set of habits, a few SQL patterns, and a documented access process. This article gives you all three. It is not legal advice. Your privacy officer and counsel decide what your organization may do, and state law can be stricter than HIPAA.

What you will take away
A map of where PHI sits in Clarity, the HIPAA rules that apply to an analyst’s daily work, SQL patterns for aggregation, small-cell suppression, date and ZIP generalization, masked views and row-level security, a decision tree for exports, an access request template, and a downloadable PDF checklist.

Where PHI Lives in Epic Clarity

HIPAA defines protected health information as individually identifiable health information. Data becomes PHI when health information combines with any of 18 identifier types listed in the Privacy Rule. Clarity holds both halves in the same database, often in neighboring tables.

Diagnosis, order, and encounter tables carry health information. Patient and encounter tables carry identifiers. A join between them creates PHI, even when each table looks harmless alone. The table below maps common identifiers to typical Clarity locations.

HIPAA identifier Typical Clarity location Risk note
Names PATIENT.PAT_NAME, PATIENT.PAT_FIRST_NAME Never needed for count or trend queries.
Medical record number PATIENT.PAT_MRN_ID Treated as an identifier even though it is internal.
Dates (birth, admission, discharge, service) PATIENT.BIRTH_DATE, PAT_ENC.CONTACT_DATE, PAT_ENC_HSP.HOSP_ADMSN_TIME All elements of a date except year are identifiers under Safe Harbor.
Geographic data below state PATIENT.ADD_LINE_1, CITY, ZIP Only the first three ZIP digits may survive, and only for large areas.
Phone, email, fax PATIENT.HOME_PHONE, EMAIL_ADDRESS Also appear in free text and contact tables.
Social Security number PATIENT.SSN (restricted at many sites) Access is commonly locked down. Do not request it.
Account and encounter numbers PAT_ENC_CSN_ID, HSP_ACCOUNT_ID Linkable to a person by anyone with source access.
Ages over 89 Computed from BIRTH_DATE Must roll up into one category, such as 90 or older.
Any unique code or characteristic Rare diagnosis plus small department Small cells can identify a person without any listed identifier.

Names above follow standard Clarity but vary by version and security configuration. Many organizations restrict or remove some columns from analyst views. Check the Clarity Data Dictionary and your site’s access roles. Assume anything dated, geographic, or numeric about a person is an identifier until you prove otherwise.

A CSN is an identifier, even though it is not on the list by name

Analysts often assume an encounter ID is harmless because it looks like a random number. It is not. Anyone with Epic access can look up the patient from a CSN in seconds. Treat it as an account-number-type identifier, and strip it from anything that leaves the secured environment. The PAT_ENC table guide shows why the CSN is also the join key. That makes it easy to carry into an export by accident.

HIPAA Rules That Shape an Analyst’s Queries

Three parts of HIPAA govern most analytics work: the Privacy Rule, the Security Rule, and the Breach Notification Rule. Each affects the SQL you write, the places you store results, and what you do when something goes wrong.

Rule Citation What it means for a Clarity query
Minimum necessary 45 CFR 164.502(b), 164.514(d) Request and use only the data the task needs. Applies to operations and analytics, not to treatment.
De-identification 45 CFR 164.514(a) to (c) Data meeting Safe Harbor or Expert Determination is no longer PHI.
Limited data set 45 CFR 164.514(e) Removes direct identifiers but keeps dates and some geography. Requires a data use agreement.
Access control 45 CFR 164.312(a) Unique user IDs, role-based access, and automatic logoff apply to database tools.
Audit controls 45 CFR 164.312(b) Systems must record and examine activity. Your queries may be logged.
Workforce training 45 CFR 164.530(b) You must be trained on policies before you touch PHI.
Breach notification 45 CFR 164.400 to 414 Impermissible disclosure triggers a risk assessment and possibly notification.

The HHS minimum necessary guidance states that covered entities must make reasonable efforts to limit PHI to the minimum necessary. The standard does not apply to disclosures for treatment, which is why a clinician can see a full chart while an analyst cannot.

Three paths to using patient data in analytics

You have three legitimate ways to work with patient-derived data. Each trades detail for protection, and each has a different approval path.

Path What you remove What you keep Approval needed
Use as PHI for operations Nothing Everything, within minimum necessary Role-based access and a documented purpose
Limited data set Names, street address, phone, MRN, and other direct identifiers Dates, city, state, ZIP Data use agreement with the recipient
De-identified (Safe Harbor) All 18 identifier types Year, state, first three ZIP digits where allowed None under HIPAA once truly de-identified
De-identified (Expert Determination) Whatever the expert specifies More detail than Safe Harbor Qualified statistician’s written determination

The HHS de-identification guidance explains both methods and the 18 identifiers. Safe Harbor also requires that you have no actual knowledge that the remaining data could identify a person. Rare diagnoses in small facilities can fail that test.

Scenario: A UAT Evidence File with 2,000 MRNs Sent by Email

A regional health system was testing a new referral workflow before go-live. A QA analyst needed to prove that referral orders reached the right departments. She joined patients, encounters, and orders in Clarity and exported 2,000 rows to Excel. Then she emailed the file to a vendor consultant as test evidence.

The file held MRNs, birth dates, encounter dates, and diagnosis names. The vendor consultant’s email address was correct, but the vendor contract did not cover PHI from the production environment. The privacy office learned of it two days later during a routine mail review.

SEC-0932  |  Production PHI emailed to vendor as UAT evidenceCritical
EnvironmentClarity production reporting server, corporate email
Reported byPrivacy office (mail review)
What happenedRow-level export (2,000 rows) with MRN, birth date, encounter date, and diagnosis sent outside the organization.
Root cause1. Evidence requirement said “attach query results” without specifying a de-identified format.
2. No masked view available for UAT.
3. No pre-send check for exports.
Immediate actionsRecall request to vendor, written attestation of deletion, risk assessment by the privacy officer.
Process fixEvidence standard: counts and screenshots with identifiers masked. Row-level data stays inside the secured environment.

The privacy officer documented a risk assessment and decided on next steps. That decision belongs to compliance, and analysts should not guess at the outcome. What I could control was the test process. The team rewrote the evidence rule and built a masked reporting view.

The before query

Before: names, MRN, birth date, dates
-- BEFORE: row-level PHI exported as test evidence
SELECT  p.PAT_MRN_ID, p.PAT_NAME, p.BIRTH_DATE,
        e.PAT_ENC_CSN_ID, e.CONTACT_DATE,
        o.ORDER_PROC_ID, o.DESCRIPTION,
        dx.DX_NAME
FROM    PATIENT p
JOIN    PAT_ENC e        ON e.PAT_ID = p.PAT_ID
JOIN    ORDER_PROC o     ON o.PAT_ENC_CSN_ID = e.PAT_ENC_CSN_ID
JOIN    PAT_ENC_DX x     ON x.PAT_ENC_CSN_ID = e.PAT_ENC_CSN_ID
JOIN    CLARITY_EDG dx   ON dx.DX_ID = x.DX_ID
WHERE   o.DESCRIPTION LIKE '%REFERRAL%'
  AND   e.CONTACT_DATE >= '2026-09-01';

The after query

After: counts only
-- AFTER: aggregate evidence, no identifiers, small cells suppressed
SELECT  d.DEPARTMENT_NAME           AS referral_department,
        DATEFROMPARTS(YEAR(e.CONTACT_DATE), MONTH(e.CONTACT_DATE), 1) AS month_start,
        COUNT(DISTINCT o.ORDER_PROC_ID) AS referral_orders
FROM    ORDER_PROC o
JOIN    PAT_ENC e        ON e.PAT_ENC_CSN_ID = o.PAT_ENC_CSN_ID
JOIN    CLARITY_DEP d    ON d.DEPARTMENT_ID  = o.REFERRAL_DEPT_ID   -- placeholder column name
WHERE   o.DESCRIPTION LIKE '%REFERRAL%'
  AND   e.CONTACT_DATE >= '2026-09-01'
GROUP BY d.DEPARTMENT_NAME,
         DATEFROMPARTS(YEAR(e.CONTACT_DATE), MONTH(e.CONTACT_DATE), 1)
HAVING  COUNT(DISTINCT o.ORDER_PROC_ID) >= 11;

The aggregate answers the test question. Did referral orders reach the expected departments in the expected numbers? The vendor needed no names, no dates, and no MRNs. The REFERRAL_DEPT_ID column is a placeholder for whichever field your build uses to store the receiving department.

For the few cases where a tester must trace one order, use a test patient created for UAT, and cite the test MRN. Real patients do not belong in non-production evidence.

Names in this scenario are illustrative
The organization, ticket number, and counts are a composite drawn from several privacy reviews. The failure pattern is common: an evidence requirement that does not say what format is acceptable.

SQL Patterns That Reduce PHI Exposure

Six patterns cover most analytics requests. Use them in order: aggregate first, generalize second, mask third, restrict fourth.

Pattern 1: Aggregate instead of listing

Most business questions need counts, rates, or averages, not rows. Rewrite the request before you write the query. Ask what decision the number supports, and the aggregate usually answers it.

Request as received Rewritten request Query shape
“List patients with a missed follow-up” “How many patients missed a follow-up, by clinic and month?” COUNT(DISTINCT PAT_ID) with GROUP BY
“Show me the readmissions” “What is the 30-day readmission rate by unit?” Numerator and denominator counts
“Send the test patients’ results” “Did the interface deliver 50 of 50 test messages?” Count with pass/fail flag

Pattern 2: Suppress small cells

A count of one or two can identify a person, especially for a rare condition in a small clinic. CMS suppresses cells with fewer than eleven beneficiaries in its public data products. Many health systems adopt the same threshold for internal reports shared outside the care team. Check your own policy for the number.

Suppression with HAVING
SELECT  d.DEPARTMENT_NAME, dxg.DX_GROUP_NAME,
        COUNT(DISTINCT e.PAT_ID) AS patients
FROM    PAT_ENC e
JOIN    CLARITY_DEP d  ON d.DEPARTMENT_ID = e.DEPARTMENT_ID
JOIN    RPT_DX_GROUP_MAP dxg ON dxg.PAT_ENC_CSN_ID = e.PAT_ENC_CSN_ID   -- your governed mapping table
WHERE   e.CONTACT_DATE >= '2026-01-01' AND e.CONTACT_DATE < '2026-10-01'
GROUP BY d.DEPARTMENT_NAME, dxg.DX_GROUP_NAME
HAVING  COUNT(DISTINCT e.PAT_ID) >= 11;

Suppression has a weakness called differencing. If a report shows the total and all but one cell, the missing cell is easy to compute. Suppress a second cell, or publish only the totals, when both a cell and its complement are exposed.

Pattern 3: Generalize dates, ages, and ZIP codes

Age bands, year only, ZIP3 with the 20,000 rule
SELECT  CASE WHEN age_years >= 90 THEN '90+'
             WHEN age_years >= 65 THEN '65-89'
             WHEN age_years >= 40 THEN '40-64'
             WHEN age_years >= 18 THEN '18-39'
             ELSE '0-17' END                         AS age_band,
        YEAR(x.CONTACT_DATE)                         AS contact_year,
        CASE WHEN z.ZIP3 IS NULL THEN '000' ELSE z.ZIP3 END AS zip3,
        COUNT(*)                                     AS encounters
FROM   (SELECT e.CONTACT_DATE, e.PAT_ID,
               DATEDIFF(year, p.BIRTH_DATE, e.CONTACT_DATE)
                 - CASE WHEN DATEADD(year, DATEDIFF(year, p.BIRTH_DATE, e.CONTACT_DATE), p.BIRTH_DATE) > e.CONTACT_DATE
                        THEN 1 ELSE 0 END            AS age_years,
               LEFT(p.ZIP, 3)                        AS zip3_raw
        FROM PAT_ENC e JOIN PATIENT p ON p.PAT_ID = e.PAT_ID
        WHERE e.CONTACT_DATE >= '2026-01-01' AND e.CONTACT_DATE < '2026-10-01') x
LEFT JOIN RPT_ZIP3_ALLOWED z ON z.ZIP3 = x.zip3_raw   -- ZIP3 areas above 20,000 people
GROUP BY CASE WHEN age_years >= 90 THEN '90+' WHEN age_years >= 65 THEN '65-89'
              WHEN age_years >= 40 THEN '40-64' WHEN age_years >= 18 THEN '18-39' ELSE '0-17' END,
         YEAR(x.CONTACT_DATE),
         CASE WHEN z.ZIP3 IS NULL THEN '000' ELSE z.ZIP3 END;

Safe Harbor lets you keep the first three ZIP digits only when all ZIP codes sharing those digits cover more than 20,000 people. Otherwise replace them with 000. The Census Bureau publishes the population data you need to build the allowed list. Notice also that the age calculation corrects for birthdays not yet reached, which plain DATEDIFF(year) gets wrong. Generalizing dates also breaks metrics that need exact timestamps, such as a Clarity LOS calculation. Decide which reports need full dates under a limited data set.

Pattern 4: Never hash an identifier and call it de-identified

Analysts often replace the MRN with a hash and consider the data safe. It is not de-identified. The Privacy Rule says a re-identification code must not be derived from information about the individual. A hash of an MRN is derived from it, and anyone with the MRN list can recompute the hash.

Technique What it gives you Does it meet Safe Harbor?
Hash of MRN (SHA-256) Consistent pseudonym, reversible by lookup No. Derived from the identifier.
Salted hash, salt kept secret Harder to reverse without the salt No for Safe Harbor. May support a limited data set with controls.
Random surrogate key from a lookup table Consistent pseudonym with no mathematical link Yes, if the lookup table stays inside the secured environment.
Drop the identifier No linkage across extracts Yes, for this identifier.
Surrogate key table (restricted schema)
-- Random surrogate key, assigned once and stored securely
INSERT INTO rpt_secure.PAT_SURROGATE (PAT_ID, SURROGATE_KEY)
SELECT  p.PAT_ID, NEWID()
FROM    PATIENT p
WHERE   NOT EXISTS (SELECT 1 FROM rpt_secure.PAT_SURROGATE s WHERE s.PAT_ID = p.PAT_ID);

Restrict the lookup table to the few people who maintain it. Anyone who can read both the surrogate table and the source can reverse the mapping.

Where Results Go: Tool Risk Comparison

A safe query still becomes unsafe when the output lands in the wrong place. Each tool you use to view or share results carries a different exposure profile. The table below ranks the tools I see most often on Epic projects.

Destination Risk with row-level PHI Why Safer use
SQL client on the secured server Low Data stays inside controlled access and logging Preferred for investigation
Reporting Workbench inside Epic Low Epic security classes and audit trail apply Operational lists for staff with access
Governed BI platform with row-level security Low to medium Depends on role design and sharing settings Dashboards on de-identified models
Excel on a managed laptop Medium Local copies, autosave, cloud sync Aggregates only, delete on schedule
Email attachment High Leaves the environment, forwards easily, hard to recall Never for row-level PHI
Jira or ticket attachment High Broad visibility, version history keeps old files Masked screenshots and counts
Chat tools and AI assistants High Third-party processing without an agreement No PHI unless the tool is approved

Most incidents I have reviewed involved the last four rows. The analyst used the tool for convenience and never considered where a copy would persist. Make the safe path the easy path by providing a secured share and a masked view.

How Access to Clarity Usually Works

Clarity access is a local decision, and it varies more than people expect. A typical arrangement gives analysts a database login tied to an Active Directory group. The group maps to a role that can read selected tables or views on a reporting server, never the Chronicles production system.

Some sites grant broad read access to all Clarity tables for a small team of senior analysts. Others expose only curated views. The curated model costs more to maintain and removes most accidental exposure. If your organization offers it, use it.

Access model Strength Weakness
Broad read on all tables Fast investigation, no view maintenance Any query can touch any identifier. Relies on analyst discipline.
Curated reporting views Identifiers removed by design Slower to add new fields. Needs governance.
Role-based views plus row-level security Scoped to department or facility Complex to administer. Easy to misconfigure.
Request-based elevation with expiry Identified data only when justified Adds a ticket step. Needs an owner for approvals.

Ask your Clarity administrator which model you work under. If the answer is “everything,” your own habits are the only control. Apply the checklist at the end of this article to every query.

If It Goes Wrong: The First Hour

Mistakes happen, and how you respond matters more than the mistake. Analysts who report quickly keep a small problem small. Analysts who hide a mistake create a larger one.

Stop sending the data. Do not forward, delete, or edit anything yet, because the privacy team needs the original facts. Write down what you sent, to whom, when, and through which channel. Then call or message your privacy officer or security contact directly, using the incident process your organization defined.

Step Action What not to do
1 Stop further sharing or access Do not try to quietly fix it first
2 Record who, what, when, and where Do not guess at details you cannot confirm
3 Report to the privacy office immediately Do not wait for the end of the sprint
4 Preserve the evidence as instructed Do not delete files before the team says so
5 Support the risk assessment Do not decide on your own whether it is a breach
6 Fix the process after the review Do not blame the individual in the ticket

Under the Breach Notification Rule, a covered entity evaluates an impermissible use or disclosure through a documented risk assessment. That assessment considers the nature of the data, the recipient, whether it was actually viewed, and how well the risk has been reduced. Your report starts that clock.

After the review, convert the lesson into a control. The email incident above produced a masked view, a revised evidence standard, and a short training segment. A new rule alone would have been forgotten within a quarter.

Masked Evidence for Jira and Test Reports

QA teams attach screenshots to tickets all day, and each screenshot can carry an MRN, a name, or a date of birth. Build masking into the test routine rather than rely on memory at the end of a long day.

Use test patients wherever the environment allows it. Crop to the relevant field. Replace visible identifiers with a solid box rather than a blur, because blur can sometimes be reversed. Check the ticket after upload, including the attachment preview, and confirm the filename does not contain a patient name.

QA-3310  |  Referral routing: expected department not populated for test patient TP-0047Medium
EnvironmentNon-production, build 2026.4, test patient TP-0047 (synthetic)
Steps1. Place referral order for cardiology.
2. Open the referral queue and read the receiving department.
ExpectedCardiology Clinic
ActualDepartment blank. Screenshot attached with name and DOB banner masked.
Data handlingSynthetic patient only. No production PHI in this ticket.

A ticket like this gives developers what they need without carrying real patient data into a tool with broad visibility. Note the explicit data-handling line. It reminds reviewers to check, and it gives auditors a clear record.

Pattern 5: Give analysts a masked view, not the base tables

Habits fail under deadline pressure. Structure holds. Build a reporting schema with views that already exclude names, street addresses, and exact birth dates, and grant analysts access to the views only.

A de-identified view and role grants (SQL Server)
CREATE VIEW rpt_safe.vw_encounter_deid AS
SELECT  s.SURROGATE_KEY                         AS person_key,
        YEAR(e.CONTACT_DATE)                    AS contact_year,
        MONTH(e.CONTACT_DATE)                   AS contact_month,
        e.DEPARTMENT_ID,
        e.ENC_TYPE_C,
        e.APPT_STATUS_C
FROM    PAT_ENC e
JOIN    rpt_secure.PAT_SURROGATE s ON s.PAT_ID = e.PAT_ID;
GO
GRANT  SELECT ON SCHEMA::rpt_safe TO analyst_role;
DENY   SELECT ON PATIENT TO analyst_role;

A view limits what the query can return, but it does not by itself prove that the data is de-identified. Dates by month and department may still identify someone in a small clinic. Have your privacy officer approve the view design, and document the approval.

Pattern 6: Restrict rows with row-level security

Some analysts should see only one hospital or one service line. SQL Server row-level security applies a predicate to every query, so the restriction does not depend on each author remembering a WHERE clause.

Row-level security on a reporting table
CREATE FUNCTION rpt_safe.fn_dept_filter(@DEPARTMENT_ID NUMERIC(18,0))
RETURNS TABLE WITH SCHEMABINDING AS
RETURN SELECT 1 AS allowed
       FROM rpt_secure.ANALYST_DEPT_ACCESS a
       WHERE a.LOGIN_NAME = USER_NAME() AND a.DEPARTMENT_ID = @DEPARTMENT_ID;
GO
CREATE SECURITY POLICY rpt_safe.DeptPolicy
ADD FILTER PREDICATE rpt_safe.fn_dept_filter(DEPARTMENT_ID) ON rpt_safe.encounter_table
WITH (STATE = ON);

Apply this on a reporting copy or a warehouse table, not on Epic’s own Clarity tables. Epic controls those, and local changes can break upgrades. Oracle offers Virtual Private Database for the same purpose, and Snowflake has row access policies.

Decision Tree: Can You Run and Export This Query?

Run every request through this tree before you hit execute. The first two questions stop most incidents.

Do I have a documented purpose
and role-based access?

No: stop,
request access
Yes

Can an aggregate answer it?
Counts, rates, averages
Yes
No

Aggregate it
Suppress cells under the
policy threshold. Check for
differencing. Export is low risk.

Do you need row-level data?
Use the de-identified view.
Drop MRN, CSN, name, full
dates, address.

Is identifiable detail truly
required?
Ask the privacy officer first.

Row-level PHI stays inside
the secured environment
No email, no personal laptop,
no unsecured Excel or chat.
Share via approved tools only.

The tree ends in the same place for most requests: the data stays inside. Moving it out requires a business associate agreement, a data use agreement, or a documented de-identification, and those take time to arrange.

Scenario: A Vendor Asks for a Readmission Extract

A health system hired an analytics vendor to model readmission risk. The vendor asked for three years of encounters with dates, diagnoses, and ZIP codes. The project manager asked me whether the team could “just pull it.”

The answer depended on the contract and the data. With a business associate agreement in place, the health system may disclose PHI to the vendor for the covered purpose, still under minimum necessary. Without one, it cannot. Even with the agreement, the vendor did not need names, street addresses, or phone numbers.

We agreed on a limited data set. The extract kept admission and discharge dates, city, state, and ZIP, because readmission modeling needs time between encounters. It dropped names, street addresses, phone numbers, MRNs, and account numbers, and replaced the MRN with a random surrogate key. A data use agreement covered the rest.

Element Original extract request Limited data set delivered
Patient identifier MRN Random surrogate key
Name, street address, phone Included Removed
Admission and discharge dates Included Included (permitted in a limited data set)
ZIP code Five digits Five digits (permitted)
Birth date Full date Full date (permitted)
Diagnosis codes ICD-10 codes ICD-10 codes
Legal basis Not stated Business associate agreement plus data use agreement

Keeping dates mattered for the model. A Safe Harbor version would have reduced everything to year and killed the readmission interval. That is the tradeoff: more utility needs more controls. A different project might have chosen Expert Determination to keep some detail without a data use agreement.

Counsel reviewed the agreements. My role was to build the extract, test that the removed fields were absent, and document the field list that the privacy officer approved.

Template: Data Access Request for Analysts

Copy this into your ticketing system. A complete request takes five minutes to write and removes most of the back-and-forth with privacy and security teams.

Field What to write Example
Requester and role Name, team, manager QA analyst, Referral Workflow project
Purpose The decision or task the data supports Verify referral orders reach the right departments before go-live
Legal basis Operations, quality improvement, research, or other Health care operations
Data needed Fields, date range, population Order counts by department and month, Sept 2026
Identifiers needed None, or list each with a reason None
Granularity Aggregate or row-level, and why Aggregate with cells under 11 suppressed
Environment Where the query runs and where results live Clarity reporting server; results stay in the secured share
Sharing Who receives the output Project team only. No external recipients.
Retention When the output is deleted 30 days after sign-off
Approver Privacy officer or data steward Name and date

Audit Trails: Assume Every Query Leaves a Record

The Security Rule requires audit controls. In practice, your database platform, your reporting tools, and Epic’s own access logs may all record who ran what and when. Privacy teams review those logs after incidents and, at many organizations, during routine monitoring.

Write queries you would defend. Name the ticket in a comment at the top. Avoid exploratory SELECT * against patient tables, because the log shows that you touched every column. Keep a short record of why you ran each production query. When someone asks in six months, you will have an answer.

Header comment that ties a query to a purpose
/* Ticket: SEC-0932-followup | Purpose: referral order counts for UAT sign-off
   Requester: QA | Approved by: Privacy Office 2026-10-02 | Aggregate only */
SELECT d.DEPARTMENT_NAME, COUNT(DISTINCT o.ORDER_PROC_ID) AS referral_orders
FROM   ORDER_PROC o
JOIN   CLARITY_DEP d ON d.DEPARTMENT_ID = o.REFERRAL_DEPT_ID
GROUP BY d.DEPARTMENT_NAME
HAVING COUNT(DISTINCT o.ORDER_PROC_ID) >= 11;

Do not look up patients you know personally, and never browse a coworker’s record out of curiosity. Snooping is a leading source of access violations in health systems, and audit logs catch it.

Role Checklists for HIPAA-Safe Clarity Work

Business Analyst

  • Specify the data format in the requirement: aggregate, de-identified, or identified, and who approves.
  • Write “no PHI in test evidence” into the test plan.
  • Add the data access request to the project intake, not to the week before go-live.
  • Identify business associate and data use agreements before a vendor requests data.

QA Analyst

  • Use test patients in non-production. Record their MRNs in the test plan.
  • Capture screenshots with identifiers masked or cropped.
  • Check exported files for hidden columns, extra sheets, and cell comments.
  • Delete evidence on the retention schedule and log the deletion.

Data Analyst

  • Work from de-identified views by default. Request elevation with a purpose.
  • Apply small-cell suppression and check for differencing.
  • Keep surrogate key tables in a restricted schema.
  • Comment every production query with a ticket and purpose.

Common HIPAA Mistakes in Clarity Work

Mistake Why it fails Fix
Exporting row-level data for a quick check Local copies escape retention and access controls Run the check in SQL and export counts
Hashing the MRN and calling it de-identified The code is derived from the identifier Use random surrogate keys or drop the field
Pasting query results into chat tools or AI assistants Disclosure to a third party without an agreement Use approved tools only, with no PHI in prompts
Leaving dates and ZIP codes in “anonymous” extracts Both are identifiers under Safe Harbor Generalize to year and ZIP3 where allowed
Assuming test environments are safe Production copies hold real PHI Confirm the environment is scrubbed before you use it
Sharing a screenshot with a visible MRN The identifier travels with the image Crop or mask before attaching to Jira
Ignoring small cells Counts of one or two identify people Suppress below the policy threshold
The mistake that taught me the most
I once pasted a failing query result into a support ticket for the vendor, with the patient columns blanked out in the sheet. The ticket system kept the original attachment version. Always check what a tool stores, not only what it shows.

When I Would Use Each Protection

For recurring dashboards, I build de-identified views once and point all reports at them. It costs a week of setup and saves a monthly debate. For one-time validation, I aggregate and suppress. For vendor work, I start with the contract and then pick the lightest data path that supports the model.

I use full identified access only for tasks that cannot work otherwise, such as a patient-level reconciliation for a billing dispute. Those run on the secured server, under a ticket, with results stored in an approved location and deleted on schedule.

For enterprise reporting, a governed model in Caboodle with built-in masking beats ad hoc Clarity queries. Validate it with the aggregate patterns above. The Epic Clarity SQL guide and the SQL for IT Analysts hub show where to find the query patterns that support those checks.

Edge Cases That Break Clean Privacy Rules

Edge case Why it matters How to handle it
Substance use disorder records 42 CFR Part 2 adds consent requirements beyond HIPAA for covered programs Ask compliance which records carry Part 2 flags before you pull diagnosis data.
Mental health and psychotherapy notes Special protections apply under HIPAA Exclude note text from analytics unless approved.
State laws stricter than HIPAA Examples include state rules on HIV, minors, and reproductive health data HIPAA sets a floor. Confirm local requirements with counsel.
Minors and adolescents Confidential services may not be visible to parents or guardians Check proxy and confidentiality flags before building patient-facing reports.
VIP and employee patients Higher snooping risk and tighter access rules Respect restrictions. Exclusions may exist in your data.
Small populations A rare diagnosis in a rural clinic identifies a person without any direct identifier Suppress or aggregate to a higher level.
Free-text fields Notes can contain names, numbers, and addresses Exclude free text unless a scrubbing process is approved.

Legal requirements change. Confirm anything that carries regulatory weight with your privacy officer or counsel before you build on it. This article describes common practice, not a ruling on your situation.

A Pre-Run Checklist for Any Clarity Query

Check Question Pass condition
1. Purpose Can I state the decision this query supports? One sentence, written in the ticket
2. Access Do I have approved, role-based access? Access request on file
3. Minimum Does the SELECT list contain only needed columns? No names, MRN, CSN, or full dates unless justified
4. Aggregate Can counts answer this? Aggregate unless a reason is documented
5. Small cells Are cells under the threshold suppressed? HAVING clause or post-filter applied
6. Destination Where will results live? Secured share, never email or personal device
7. Retention When will I delete them? Date in the ticket

Questions Analysts Ask About HIPAA and Clarity

Is Clarity data always PHI?

Not every table, but any query that combines health information with an identifier produces PHI. Treat Clarity as PHI by default.

Can I use real patient data in a test environment?

Only if your organization has authorized it and applied the same safeguards as production. Many sites scrub non-production copies. Confirm yours is scrubbed before you rely on it.

Does removing the patient name make a dataset de-identified?

No. De-identification requires removing or generalizing all 18 identifier types, or a qualified expert’s determination. Dates, ZIP codes, and record numbers still identify people.

Is it safe to paste query results into an AI assistant?

Not unless your organization has approved that tool and signed the required agreements. Treat pasted PHI as a disclosure.

Who decides whether an incident is a breach?

Your privacy officer, using the risk assessment that the Breach Notification Rule requires. Report the incident quickly and let them decide.

Run This Before Your Next Export

Open the last query you exported and read its SELECT list. Count the identifiers: names, MRNs, CSNs, full dates, addresses. For each one, write the reason you needed it. If you cannot write a reason, rewrite the query as an aggregate. That ten-minute audit of your own work prevents the next SEC ticket.

Download the HIPAA-Safe Clarity SQL Checklist and Access Request Template (PDF)
PHI map, pre-run checklist, SQL patterns, export decision rules, and the access request template on two printable pages.

Download the PDF

Sources and Further Reading

  • HHS: Guidance Regarding Methods for De-identification of PHI. Defines Safe Harbor, the 18 identifiers, and Expert Determination.
  • HHS: Minimum Necessary Requirement. Official guidance on limiting PHI use and disclosure.
  • 45 CFR Parts 160 and 164 (HIPAA Administrative Simplification regulations) on eCFR. Citations in this article refer to these parts.
  • Epic Clarity Data Dictionary on Epic UserWeb (requires an Epic customer login). Authority for column names in your version.

This article does not constitute legal advice. Table and column names follow standard Clarity and vary by site. Placeholder objects are marked in the code.

Scroll to Top