Fixing tables due to kable update, adding fix to drug_era script
This commit is contained in:
parent
8451b5027b
commit
800dca15e2
6955
docs/cdm53.html
6955
docs/cdm53.html
File diff suppressed because it is too large
Load Diff
7563
docs/cdm54.html
7563
docs/cdm54.html
File diff suppressed because it is too large
Load Diff
7448
docs/cdm60.html
7448
docs/cdm60.html
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
||||||
|
// Pandoc 2.9 adds attributes on both header and div. We remove the former (to
|
||||||
|
// be compatible with the behavior of Pandoc < 2.8).
|
||||||
|
document.addEventListener('DOMContentLoaded', function(e) {
|
||||||
|
var hs = document.querySelectorAll("div.section[class*='level'] > :first-child");
|
||||||
|
var i, h, a;
|
||||||
|
for (i = 0; i < hs.length; i++) {
|
||||||
|
h = hs[i];
|
||||||
|
if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6
|
||||||
|
a = h.attributes;
|
||||||
|
while (a.length > 0) h.removeAttribute(a[0].name);
|
||||||
|
}
|
||||||
|
});
|
|
@ -34,7 +34,9 @@ window.initializeCodeFolding = function(show) {
|
||||||
showCodeButton.append(showCodeText);
|
showCodeButton.append(showCodeText);
|
||||||
showCodeButton
|
showCodeButton
|
||||||
.attr('data-toggle', 'collapse')
|
.attr('data-toggle', 'collapse')
|
||||||
|
.attr('data-bs-toggle', 'collapse') // BS5
|
||||||
.attr('data-target', '#' + id)
|
.attr('data-target', '#' + id)
|
||||||
|
.attr('data-bs-target', '#' + id) // BS5
|
||||||
.attr('aria-expanded', showThis)
|
.attr('aria-expanded', showThis)
|
||||||
.attr('aria-controls', id);
|
.attr('aria-controls', id);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
<title>sqlScripts.knit</title>
|
<title>sqlScripts.knit</title>
|
||||||
|
|
||||||
<script src="site_libs/header-attrs-2.11/header-attrs.js"></script>
|
<script src="site_libs/header-attrs-2.13/header-attrs.js"></script>
|
||||||
<script src="site_libs/jquery-3.6.0/jquery-3.6.0.min.js"></script>
|
<script src="site_libs/jquery-3.6.0/jquery-3.6.0.min.js"></script>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link href="site_libs/bootstrap-3.3.5/css/cosmo.min.css" rel="stylesheet" />
|
<link href="site_libs/bootstrap-3.3.5/css/cosmo.min.css" rel="stylesheet" />
|
||||||
|
@ -63,6 +63,7 @@ if (window.hljs) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="style.css" type="text/css" />
|
<link rel="stylesheet" href="style.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,6 +89,9 @@ button.code-folding-btn:focus {
|
||||||
summary {
|
summary {
|
||||||
display: list-item;
|
display: list-item;
|
||||||
}
|
}
|
||||||
|
details > summary > p:only-child {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
pre code {
|
pre code {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
@ -312,7 +316,7 @@ div.tocify {
|
||||||
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar">
|
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-bs-toggle="collapse" data-target="#navbar" data-bs-target="#navbar">
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
|
@ -328,7 +332,7 @@ div.tocify {
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<span class="fa fa-landmark"></span>
|
<span class="fa fa-landmark"></span>
|
||||||
|
|
||||||
Background
|
Background
|
||||||
|
@ -348,7 +352,7 @@ div.tocify {
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<span class="fa fa-list-alt"></span>
|
<span class="fa fa-list-alt"></span>
|
||||||
|
|
||||||
Conventions
|
Conventions
|
||||||
|
@ -368,7 +372,7 @@ div.tocify {
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<span class="fa fa-history"></span>
|
<span class="fa fa-history"></span>
|
||||||
|
|
||||||
CDM Versions
|
CDM Versions
|
||||||
|
@ -386,7 +390,7 @@ div.tocify {
|
||||||
<a href="cdm53.html">CDM v5.3</a>
|
<a href="cdm53.html">CDM v5.3</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-submenu">
|
<li class="dropdown-submenu">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">NEW CDM v5.4</a>
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">NEW CDM v5.4</a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
<li>
|
<li>
|
||||||
<a href="cdm54.html">CDM v5.4</a>
|
<a href="cdm54.html">CDM v5.4</a>
|
||||||
|
@ -399,7 +403,7 @@ div.tocify {
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<span class="fa fa-plus-square"></span>
|
<span class="fa fa-plus-square"></span>
|
||||||
|
|
||||||
Proposals
|
Proposals
|
||||||
|
@ -411,7 +415,7 @@ div.tocify {
|
||||||
<a href="https://github.com/OHDSI/CommonDataModel/issues?q=is%3Aopen+is%3Aissue+label%3AProposal">Under Review</a>
|
<a href="https://github.com/OHDSI/CommonDataModel/issues?q=is%3Aopen+is%3Aissue+label%3AProposal">Under Review</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-submenu">
|
<li class="dropdown-submenu">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Accepted</a>
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">Accepted</a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
<li>
|
<li>
|
||||||
<a href="https://github.com/OHDSI/CommonDataModel/issues/252">Region_concept_id</a>
|
<a href="https://github.com/OHDSI/CommonDataModel/issues/252">Region_concept_id</a>
|
||||||
|
@ -421,7 +425,7 @@ div.tocify {
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<span class="fa fa-question"></span>
|
<span class="fa fa-question"></span>
|
||||||
|
|
||||||
How to
|
How to
|
||||||
|
@ -441,7 +445,7 @@ div.tocify {
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<span class="fa fa-life-ring"></span>
|
<span class="fa fa-life-ring"></span>
|
||||||
|
|
||||||
Support
|
Support
|
||||||
|
@ -700,174 +704,168 @@ GROUP BY person_id
|
||||||
<h3>Drug Eras</h3>
|
<h3>Drug Eras</h3>
|
||||||
<p>If the DRUG_EXPOSURE table is populated this script will string together periods of time that a person is exposed to an active drug ingredient, allowing for 30 gaps in between. It will then insert the resulting era records into the DRUG_ERA table. <strong>NOTE</strong> This query only works with 5.3 and below.</p>
|
<p>If the DRUG_EXPOSURE table is populated this script will string together periods of time that a person is exposed to an active drug ingredient, allowing for 30 gaps in between. It will then insert the resulting era records into the DRUG_ERA table. <strong>NOTE</strong> This query only works with 5.3 and below.</p>
|
||||||
<pre class="sql"><code>
|
<pre class="sql"><code>
|
||||||
/****************************************************
|
-- Code taken from:
|
||||||
OHDSI-SQL File Instructions
|
-- https://github.com/OHDSI/ETL-CMS/blob/master/SQL/create_CDMv5_drug_era_non_stockpile.sql
|
||||||
-----------------------------
|
|
||||||
1. Set parameter name of schema that contains CDMv4 instance
|
|
||||||
(@SOURCE_CDMV4, @SOURCE_CDMV4_SCHEMA)
|
|
||||||
2. Set parameter name of schema that contains CDMv5 instance
|
|
||||||
(@TARGET_CDMV5, @TARGET_CDMV5_SCHEMA)
|
|
||||||
3. Run this script through SqlRender to produce a script that will work in your
|
|
||||||
source dialect. SqlRender can be found here: https://github.com/OHDSI/SqlRender
|
|
||||||
4. Run the script produced by SQL Render on your target RDBDMS.
|
|
||||||
<RDBMS> File Instructions
|
|
||||||
-------------------------
|
|
||||||
1. This script will hold a number of placeholders for your CDM V4 and CDMV5
|
|
||||||
database/schema. In order to make this file work in your environment, you
|
|
||||||
should plan to do a global "FIND AND REPLACE" on this file to fill in the
|
|
||||||
file with values that pertain to your environment. The following are the
|
|
||||||
tokens you should use when doing your "FIND AND REPLACE" operation:
|
|
||||||
|
|
||||||
[CDM]
|
|
||||||
[CDM].[CDMSCHEMA]
|
|
||||||
|
|
||||||
*********************************************************************************/
|
|
||||||
/* SCRIPT PARAMETERS */
|
|
||||||
|
|
||||||
|
|
||||||
{DEFAULT @TARGET_CDMV5 = '[CDM]' } -- The target CDMv5 database name
|
if object_id('tempdb..#tmp_de', 'U') is not null drop table #tmp_de;
|
||||||
{DEFAULT @TARGET_CDMV5_SCHEMA = '[CDM].[CDMSCHEMA]' } -- the target CDMv5 database plus schema
|
|
||||||
|
|
||||||
USE @TARGET_CDMV5;
|
WITH
|
||||||
|
ctePreDrugTarget(drug_exposure_id, person_id, ingredient_concept_id, drug_exposure_start_date, days_supply, drug_exposure_end_date) AS
|
||||||
|
(-- Normalize DRUG_EXPOSURE_END_DATE to either the existing drug exposure end date, or add days supply, or add 1 day to the start date
|
||||||
|
SELECT
|
||||||
|
d.drug_exposure_id
|
||||||
|
, d.person_id
|
||||||
|
, c.concept_id AS ingredient_concept_id
|
||||||
|
, d.drug_exposure_start_date AS drug_exposure_start_date
|
||||||
|
, d.days_supply AS days_supply
|
||||||
|
, COALESCE(
|
||||||
|
---NULLIF returns NULL if both values are the same, otherwise it returns the first parameter
|
||||||
|
NULLIF(drug_exposure_end_date, NULL),
|
||||||
|
---If drug_exposure_end_date != NULL, return drug_exposure_end_date, otherwise go to next case
|
||||||
|
NULLIF(dateadd(day,days_supply,drug_exposure_start_date), drug_exposure_start_date),
|
||||||
|
---If days_supply != NULL or 0, return drug_exposure_start_date + days_supply, otherwise go to next case
|
||||||
|
dateadd(day,1,drug_exposure_start_date)
|
||||||
|
---Add 1 day to the drug_exposure_start_date since there is no end_date or INTERVAL for the days_supply
|
||||||
|
) AS drug_exposure_end_date
|
||||||
|
FROM @cdm_schema.drug_exposure d
|
||||||
|
JOIN @cdm_schema.concept_ancestor ca ON ca.descendant_concept_id = d.drug_concept_id
|
||||||
|
JOIN @cdm_schema.concept c ON ca.ancestor_concept_id = c.concept_id
|
||||||
|
WHERE c.vocabulary_id = 'RxNorm' ---8 selects RxNorm from the vocabulary_id
|
||||||
|
AND c.concept_class_id = 'Ingredient'
|
||||||
|
AND d.drug_concept_id != 0 ---Our unmapped drug_concept_id's are set to 0, so we don't want different drugs wrapped up in the same era
|
||||||
|
AND coalesce(d.days_supply,0) >= 0 ---We have cases where days_supply is negative, and this can set the end_date before the start_date, which we don't want. So we're just looking over those rows. This is a data-quality issue.
|
||||||
|
)
|
||||||
|
|
||||||
|
, cteSubExposureEndDates (person_id, ingredient_concept_id, end_date) AS --- A preliminary sorting that groups all of the overlapping exposures into one exposure so that we don't double-count non-gap-days
|
||||||
|
(
|
||||||
/****
|
SELECT person_id, ingredient_concept_id, event_date AS end_date
|
||||||
DRUG ERA
|
FROM
|
||||||
Note: Eras derived from DRUG_EXPOSURE table, using 30d gap
|
(
|
||||||
****/
|
SELECT person_id, ingredient_concept_id, event_date, event_type,
|
||||||
IF OBJECT_ID('tempdb..#cteDrugTarget', 'U') IS NOT NULL
|
MAX(start_ordinal) OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
DROP TABLE #cteDrugTarget;
|
ORDER BY event_date, event_type ROWS unbounded preceding) AS start_ordinal,
|
||||||
|
-- this pulls the current START down from the prior rows so that the NULLs
|
||||||
/* / */
|
-- from the END DATES will contain a value we can compare with
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
-- Normalize DRUG_EXPOSURE_END_DATE to either the existing drug exposure end date, or add days supply, or add 1 day to the start date
|
ORDER BY event_date, event_type) AS overall_ord
|
||||||
SELECT d.DRUG_EXPOSURE_ID
|
-- this re-numbers the inner UNION so all rows are numbered ordered by the event date
|
||||||
,d.PERSON_ID
|
|
||||||
,c.CONCEPT_ID
|
|
||||||
,d.DRUG_TYPE_CONCEPT_ID
|
|
||||||
,DRUG_EXPOSURE_START_DATE
|
|
||||||
,COALESCE(DRUG_EXPOSURE_END_DATE, DATEADD(day, DAYS_SUPPLY, DRUG_EXPOSURE_START_DATE), DATEADD(day, 1, DRUG_EXPOSURE_START_DATE)) AS DRUG_EXPOSURE_END_DATE
|
|
||||||
,c.CONCEPT_ID AS INGREDIENT_CONCEPT_ID
|
|
||||||
INTO #cteDrugTarget
|
|
||||||
FROM @TARGET_CDMV5_SCHEMA.DRUG_EXPOSURE d
|
|
||||||
INNER JOIN @TARGET_CDMV5_SCHEMA.CONCEPT_ANCESTOR ca ON ca.DESCENDANT_CONCEPT_ID = d.DRUG_CONCEPT_ID
|
|
||||||
INNER JOIN @TARGET_CDMV5_SCHEMA.CONCEPT c ON ca.ANCESTOR_CONCEPT_ID = c.CONCEPT_ID
|
|
||||||
WHERE c.DOMAIN_ID = 'Drug'
|
|
||||||
AND c.CONCEPT_CLASS_ID = 'Ingredient'
|
|
||||||
AND c.STANDARD_CONCEPT = 'S';
|
|
||||||
|
|
||||||
/* / */
|
|
||||||
|
|
||||||
IF OBJECT_ID('tempdb..#cteEndDates', 'U') IS NOT NULL
|
|
||||||
DROP TABLE #cteEndDates;
|
|
||||||
|
|
||||||
/* / */
|
|
||||||
|
|
||||||
SELECT PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID
|
|
||||||
,DATEADD(day, - 30, EVENT_DATE) AS END_DATE -- unpad the end date
|
|
||||||
INTO #cteEndDates
|
|
||||||
FROM (
|
|
||||||
SELECT E1.PERSON_ID
|
|
||||||
,E1.INGREDIENT_CONCEPT_ID
|
|
||||||
,E1.EVENT_DATE
|
|
||||||
,COALESCE(E1.START_ORDINAL, MAX(E2.START_ORDINAL)) START_ORDINAL
|
|
||||||
,E1.OVERALL_ORD
|
|
||||||
FROM (
|
|
||||||
SELECT PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID
|
|
||||||
,EVENT_DATE
|
|
||||||
,EVENT_TYPE
|
|
||||||
,START_ORDINAL
|
|
||||||
,ROW_NUMBER() OVER (
|
|
||||||
PARTITION BY PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID ORDER BY EVENT_DATE
|
|
||||||
,EVENT_TYPE
|
|
||||||
) AS OVERALL_ORD -- this re-numbers the inner UNION so all rows are numbered ordered by the event date
|
|
||||||
FROM (
|
FROM (
|
||||||
-- select the start dates, assigning a row number to each
|
-- select the start dates, assigning a row number to each
|
||||||
SELECT PERSON_ID
|
SELECT person_id, ingredient_concept_id, drug_exposure_start_date AS event_date,
|
||||||
,INGREDIENT_CONCEPT_ID
|
-1 AS event_type,
|
||||||
,DRUG_EXPOSURE_START_DATE AS EVENT_DATE
|
ROW_NUMBER() OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
,0 AS EVENT_TYPE
|
ORDER BY drug_exposure_start_date) AS start_ordinal
|
||||||
,ROW_NUMBER() OVER (
|
FROM ctePreDrugTarget
|
||||||
PARTITION BY PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID ORDER BY DRUG_EXPOSURE_START_DATE
|
|
||||||
) AS START_ORDINAL
|
|
||||||
FROM #cteDrugTarget
|
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
-- add the end dates with NULL as the row number, padding the end dates by 30 to allow a grace period for overlapping ranges.
|
SELECT person_id, ingredient_concept_id, drug_exposure_end_date, 1 AS event_type, NULL
|
||||||
SELECT PERSON_ID
|
FROM ctePreDrugTarget
|
||||||
,INGREDIENT_CONCEPT_ID
|
|
||||||
,DATEADD(day, 30, DRUG_EXPOSURE_END_DATE)
|
|
||||||
,1 AS EVENT_TYPE
|
|
||||||
,NULL
|
|
||||||
FROM #cteDrugTarget
|
|
||||||
) RAWDATA
|
) RAWDATA
|
||||||
) E1
|
) e
|
||||||
INNER JOIN (
|
WHERE (2 * e.start_ordinal) - e.overall_ord = 0
|
||||||
SELECT PERSON_ID
|
)
|
||||||
,INGREDIENT_CONCEPT_ID
|
|
||||||
,DRUG_EXPOSURE_START_DATE AS EVENT_DATE
|
|
||||||
,ROW_NUMBER() OVER (
|
|
||||||
PARTITION BY PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID ORDER BY DRUG_EXPOSURE_START_DATE
|
|
||||||
) AS START_ORDINAL
|
|
||||||
FROM #cteDrugTarget
|
|
||||||
) E2 ON E1.PERSON_ID = E2.PERSON_ID
|
|
||||||
AND E1.INGREDIENT_CONCEPT_ID = E2.INGREDIENT_CONCEPT_ID
|
|
||||||
AND E2.EVENT_DATE <= E1.EVENT_DATE
|
|
||||||
GROUP BY E1.PERSON_ID
|
|
||||||
,E1.INGREDIENT_CONCEPT_ID
|
|
||||||
,E1.EVENT_DATE
|
|
||||||
,E1.START_ORDINAL
|
|
||||||
,E1.OVERALL_ORD
|
|
||||||
) E
|
|
||||||
WHERE 2 * E.START_ORDINAL - E.OVERALL_ORD = 0;
|
|
||||||
|
|
||||||
/* / */
|
, cteDrugExposureEnds (person_id, drug_concept_id, drug_exposure_start_date, drug_sub_exposure_end_date) AS
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
dt.person_id
|
||||||
|
, dt.ingredient_concept_id
|
||||||
|
, dt.drug_exposure_start_date
|
||||||
|
, MIN(e.end_date) AS drug_sub_exposure_end_date
|
||||||
|
FROM ctePreDrugTarget dt
|
||||||
|
JOIN cteSubExposureEndDates e ON dt.person_id = e.person_id AND dt.ingredient_concept_id = e.ingredient_concept_id AND e.end_date >= dt.drug_exposure_start_date
|
||||||
|
GROUP BY
|
||||||
|
dt.drug_exposure_id
|
||||||
|
, dt.person_id
|
||||||
|
, dt.ingredient_concept_id
|
||||||
|
, dt.drug_exposure_start_date
|
||||||
|
)
|
||||||
|
--------------------------------------------------------------------------------------------------------------
|
||||||
|
, cteSubExposures(row_number, person_id, drug_concept_id, drug_sub_exposure_start_date, drug_sub_exposure_end_date, drug_exposure_count) AS
|
||||||
|
(
|
||||||
|
SELECT ROW_NUMBER() OVER (PARTITION BY person_id, drug_concept_id, drug_sub_exposure_end_date ORDER BY person_id)
|
||||||
|
, person_id, drug_concept_id, MIN(drug_exposure_start_date) AS drug_sub_exposure_start_date, drug_sub_exposure_end_date, COUNT(*) AS drug_exposure_count
|
||||||
|
FROM cteDrugExposureEnds
|
||||||
|
GROUP BY person_id, drug_concept_id, drug_sub_exposure_end_date
|
||||||
|
--ORDER BY person_id, drug_concept_id
|
||||||
|
)
|
||||||
|
--------------------------------------------------------------------------------------------------------------
|
||||||
|
/*Everything above grouped exposures into sub_exposures if there was overlap between exposures.
|
||||||
|
*So there was no persistence window. Now we can add the persistence window to calculate eras.
|
||||||
|
*/
|
||||||
|
--------------------------------------------------------------------------------------------------------------
|
||||||
|
, cteFinalTarget(row_number, person_id, ingredient_concept_id, drug_sub_exposure_start_date, drug_sub_exposure_end_date, drug_exposure_count, days_exposed) AS
|
||||||
|
(
|
||||||
|
SELECT row_number, person_id, drug_concept_id, drug_sub_exposure_start_date, drug_sub_exposure_end_date, drug_exposure_count
|
||||||
|
, datediff(day,drug_sub_exposure_start_date,drug_sub_exposure_end_date) AS days_exposed
|
||||||
|
FROM cteSubExposures
|
||||||
|
)
|
||||||
|
--------------------------------------------------------------------------------------------------------------
|
||||||
|
, cteEndDates (person_id, ingredient_concept_id, end_date) AS -- the magic
|
||||||
|
(
|
||||||
|
SELECT person_id, ingredient_concept_id, dateadd(day,-30,event_date) AS end_date -- unpad the end date
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT person_id, ingredient_concept_id, event_date, event_type,
|
||||||
|
MAX(start_ordinal) OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
|
ORDER BY event_date, event_type ROWS UNBOUNDED PRECEDING) AS start_ordinal,
|
||||||
|
-- this pulls the current START down from the prior rows so that the NULLs
|
||||||
|
-- from the END DATES will contain a value we can compare with
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
|
ORDER BY event_date, event_type) AS overall_ord
|
||||||
|
-- this re-numbers the inner UNION so all rows are numbered ordered by the event date
|
||||||
|
FROM (
|
||||||
|
-- select the start dates, assigning a row number to each
|
||||||
|
SELECT person_id, ingredient_concept_id, drug_sub_exposure_start_date AS event_date,
|
||||||
|
-1 AS event_type,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
|
ORDER BY drug_sub_exposure_start_date) AS start_ordinal
|
||||||
|
FROM cteFinalTarget
|
||||||
|
|
||||||
IF OBJECT_ID('tempdb..#cteDrugExpEnds', 'U') IS NOT NULL
|
UNION ALL
|
||||||
DROP TABLE #cteDrugExpEnds;
|
|
||||||
|
|
||||||
/* / */
|
-- pad the end dates by 30 to allow a grace period for overlapping ranges.
|
||||||
|
SELECT person_id, ingredient_concept_id, dateadd(day,30,drug_sub_exposure_end_date), 1 AS event_type, NULL
|
||||||
|
FROM cteFinalTarget
|
||||||
|
) RAWDATA
|
||||||
|
) e
|
||||||
|
WHERE (2 * e.start_ordinal) - e.overall_ord = 0
|
||||||
|
|
||||||
SELECT d.PERSON_ID
|
)
|
||||||
,d.INGREDIENT_CONCEPT_ID
|
, cteDrugEraEnds (person_id, drug_concept_id, drug_sub_exposure_start_date, drug_era_end_date, drug_exposure_count, days_exposed) AS
|
||||||
,d.DRUG_TYPE_CONCEPT_ID
|
(
|
||||||
,d.DRUG_EXPOSURE_START_DATE
|
SELECT
|
||||||
,MIN(e.END_DATE) AS ERA_END_DATE
|
ft.person_id
|
||||||
INTO #cteDrugExpEnds
|
, ft.ingredient_concept_id
|
||||||
FROM #cteDrugTarget d
|
, ft.drug_sub_exposure_start_date
|
||||||
INNER JOIN #cteEndDates e ON d.PERSON_ID = e.PERSON_ID
|
, MIN(e.end_date) AS era_end_date
|
||||||
AND d.INGREDIENT_CONCEPT_ID = e.INGREDIENT_CONCEPT_ID
|
, drug_exposure_count
|
||||||
AND e.END_DATE >= d.DRUG_EXPOSURE_START_DATE
|
, days_exposed
|
||||||
GROUP BY d.PERSON_ID
|
FROM cteFinalTarget ft
|
||||||
,d.INGREDIENT_CONCEPT_ID
|
JOIN cteEndDates e ON ft.person_id = e.person_id AND ft.ingredient_concept_id = e.ingredient_concept_id AND e.end_date >= ft.drug_sub_exposure_start_date
|
||||||
,d.DRUG_TYPE_CONCEPT_ID
|
GROUP BY
|
||||||
,d.DRUG_EXPOSURE_START_DATE;
|
ft.person_id
|
||||||
|
, ft.ingredient_concept_id
|
||||||
/* / */
|
, ft.drug_sub_exposure_start_date
|
||||||
|
, drug_exposure_count
|
||||||
INSERT INTO @TARGET_CDMV5_SCHEMA.drug_era
|
, days_exposed
|
||||||
SELECT row_number() OVER (
|
)
|
||||||
ORDER BY person_id
|
SELECT
|
||||||
) AS drug_era_id
|
row_number()over(order by person_id) drug_era_id
|
||||||
, person_id
|
, person_id
|
||||||
,INGREDIENT_CONCEPT_ID
|
, drug_concept_id
|
||||||
,min(DRUG_EXPOSURE_START_DATE) AS drug_era_start_date
|
, MIN(drug_sub_exposure_start_date) AS drug_era_start_date
|
||||||
,ERA_END_DATE
|
, drug_era_end_date
|
||||||
,COUNT(*) AS DRUG_EXPOSURE_COUNT
|
, SUM(drug_exposure_count) AS drug_exposure_count
|
||||||
,30 AS gap_days
|
, datediff(day,MIN(drug_sub_exposure_start_date),drug_era_end_date)-SUM(days_exposed) as gap_days
|
||||||
FROM #cteDrugExpEnds
|
INTO #tmp_de
|
||||||
GROUP BY person_id
|
FROM cteDrugEraEnds dee
|
||||||
,INGREDIENT_CONCEPT_ID
|
GROUP BY person_id, drug_concept_id, drug_era_end_date;
|
||||||
,drug_type_concept_id
|
|
||||||
,ERA_END_DATE;
|
INSERT INTO @cdm_schema.drug_era(drug_era_id,person_id, drug_concept_id, drug_era_start_date, drug_era_end_date, drug_exposure_count, gap_days)
|
||||||
</code></pre>
|
SELECT * FROM #tmp_de;</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="example-etl-script" class="section level2">
|
<div id="example-etl-script" class="section level2">
|
||||||
|
|
|
@ -92,9 +92,9 @@ for(tb in tables) {
|
||||||
|
|
||||||
print(kable(x = loopTable, align = "l", row.names = FALSE, format = "html", escape = FALSE) %>%
|
print(kable(x = loopTable, align = "l", row.names = FALSE, format = "html", escape = FALSE) %>%
|
||||||
column_spec(1, bold = T) %>%
|
column_spec(1, bold = T) %>%
|
||||||
column_spec(2, width = "3in", include_thead = T) %>%
|
# column_spec(2, width = "3in", include_thead = T) %>%
|
||||||
column_spec(3, width = "4in", include_thead = T) %>%
|
# column_spec(3, width = "4in", include_thead = T) %>%
|
||||||
column_spec(4:9, width = "1in", include_thead = T) %>%
|
# column_spec(4:9, width = "1in", include_thead = T) %>%
|
||||||
kable_styling(c("condensed","hover"), position = "center", full_width = T, font_size = 13))
|
kable_styling(c("condensed","hover"), position = "center", full_width = T, font_size = 13))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -108,9 +108,9 @@ for(tb in tables) {
|
||||||
|
|
||||||
print(kable(x = loopTable, align = "l", row.names = FALSE, format = "html", escape = FALSE) %>%
|
print(kable(x = loopTable, align = "l", row.names = FALSE, format = "html", escape = FALSE) %>%
|
||||||
column_spec(1, bold = T) %>%
|
column_spec(1, bold = T) %>%
|
||||||
column_spec(2, width = "3in", include_thead = T) %>%
|
# column_spec(2, width = "3in", include_thead = T) %>%
|
||||||
column_spec(3, width = "4in", include_thead = T) %>%
|
# column_spec(3, width = "4in", include_thead = T) %>%
|
||||||
column_spec(4:9, width = "1in", include_thead = T) %>%
|
# column_spec(4:9, width = "1in", include_thead = T) %>%
|
||||||
kable_styling(c("condensed","hover"), position = "center", full_width = T, font_size = 13))
|
kable_styling(c("condensed","hover"), position = "center", full_width = T, font_size = 13))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -104,9 +104,9 @@ for(tb in tables) {
|
||||||
|
|
||||||
print(kable(x = loopTable, align = "l", row.names = FALSE, format = "html") %>%
|
print(kable(x = loopTable, align = "l", row.names = FALSE, format = "html") %>%
|
||||||
column_spec(1, bold = T) %>%
|
column_spec(1, bold = T) %>%
|
||||||
column_spec(2, width = "3in", include_thead = T) %>%
|
# column_spec(2, width = "3in", include_thead = T) %>%
|
||||||
column_spec(3, width = "4in", include_thead = T) %>%
|
# column_spec(3, width = "4in", include_thead = T) %>%
|
||||||
column_spec(4:9, width = "1in", include_thead = T) %>%
|
# column_spec(4:9, width = "1in", include_thead = T) %>%
|
||||||
kable_styling(c("condensed","hover"), position = "center", full_width = T, font_size = 13))
|
kable_styling(c("condensed","hover"), position = "center", full_width = T, font_size = 13))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -232,178 +232,172 @@ GROUP BY person_id
|
||||||
|
|
||||||
### Drug Eras
|
### Drug Eras
|
||||||
|
|
||||||
If the DRUG_EXPOSURE table is populated this script will string together periods of time that a person is exposed to an active drug ingredient, allowing for 30 gaps in between. It will then insert the resulting era records into the DRUG_ERA table. **NOTE** This query only works with 5.3 and below.
|
If the DRUG_EXPOSURE table is populated this script will string together periods of time that a person is exposed to an active drug ingredient, allowing for 30 gaps in between. It will then insert the resulting era records into the DRUG_ERA table. **NOTE** This query only works with the **version 5** series and below.
|
||||||
|
|
||||||
```{sql eval = FALSE, echo = TRUE}
|
```{sql eval = FALSE, echo = TRUE}
|
||||||
|
|
||||||
/****************************************************
|
-- Code taken from:
|
||||||
OHDSI-SQL File Instructions
|
-- https://github.com/OHDSI/ETL-CMS/blob/master/SQL/create_CDMv5_drug_era_non_stockpile.sql
|
||||||
-----------------------------
|
|
||||||
1. Set parameter name of schema that contains CDMv4 instance
|
|
||||||
(@SOURCE_CDMV4, @SOURCE_CDMV4_SCHEMA)
|
|
||||||
2. Set parameter name of schema that contains CDMv5 instance
|
|
||||||
(@TARGET_CDMV5, @TARGET_CDMV5_SCHEMA)
|
|
||||||
3. Run this script through SqlRender to produce a script that will work in your
|
|
||||||
source dialect. SqlRender can be found here: https://github.com/OHDSI/SqlRender
|
|
||||||
4. Run the script produced by SQL Render on your target RDBDMS.
|
|
||||||
<RDBMS> File Instructions
|
|
||||||
-------------------------
|
|
||||||
1. This script will hold a number of placeholders for your CDM V4 and CDMV5
|
|
||||||
database/schema. In order to make this file work in your environment, you
|
|
||||||
should plan to do a global "FIND AND REPLACE" on this file to fill in the
|
|
||||||
file with values that pertain to your environment. The following are the
|
|
||||||
tokens you should use when doing your "FIND AND REPLACE" operation:
|
|
||||||
|
|
||||||
[CDM]
|
|
||||||
[CDM].[CDMSCHEMA]
|
|
||||||
|
|
||||||
*********************************************************************************/
|
|
||||||
/* SCRIPT PARAMETERS */
|
|
||||||
|
|
||||||
|
|
||||||
{DEFAULT @TARGET_CDMV5 = '[CDM]' } -- The target CDMv5 database name
|
if object_id('tempdb..#tmp_de', 'U') is not null drop table #tmp_de;
|
||||||
{DEFAULT @TARGET_CDMV5_SCHEMA = '[CDM].[CDMSCHEMA]' } -- the target CDMv5 database plus schema
|
|
||||||
|
|
||||||
USE @TARGET_CDMV5;
|
WITH
|
||||||
|
ctePreDrugTarget(drug_exposure_id, person_id, ingredient_concept_id, drug_exposure_start_date, days_supply, drug_exposure_end_date) AS
|
||||||
|
(-- Normalize DRUG_EXPOSURE_END_DATE to either the existing drug exposure end date, or add days supply, or add 1 day to the start date
|
||||||
|
SELECT
|
||||||
|
d.drug_exposure_id
|
||||||
|
, d.person_id
|
||||||
|
, c.concept_id AS ingredient_concept_id
|
||||||
|
, d.drug_exposure_start_date AS drug_exposure_start_date
|
||||||
|
, d.days_supply AS days_supply
|
||||||
|
, COALESCE(
|
||||||
|
---NULLIF returns NULL if both values are the same, otherwise it returns the first parameter
|
||||||
|
NULLIF(drug_exposure_end_date, NULL),
|
||||||
|
---If drug_exposure_end_date != NULL, return drug_exposure_end_date, otherwise go to next case
|
||||||
|
NULLIF(dateadd(day,days_supply,drug_exposure_start_date), drug_exposure_start_date),
|
||||||
|
---If days_supply != NULL or 0, return drug_exposure_start_date + days_supply, otherwise go to next case
|
||||||
|
dateadd(day,1,drug_exposure_start_date)
|
||||||
|
---Add 1 day to the drug_exposure_start_date since there is no end_date or INTERVAL for the days_supply
|
||||||
|
) AS drug_exposure_end_date
|
||||||
|
FROM @cdm_schema.drug_exposure d
|
||||||
|
JOIN @cdm_schema.concept_ancestor ca ON ca.descendant_concept_id = d.drug_concept_id
|
||||||
|
JOIN @cdm_schema.concept c ON ca.ancestor_concept_id = c.concept_id
|
||||||
|
WHERE c.vocabulary_id = 'RxNorm' ---8 selects RxNorm from the vocabulary_id
|
||||||
|
AND c.concept_class_id = 'Ingredient'
|
||||||
|
AND d.drug_concept_id != 0 ---Our unmapped drug_concept_id's are set to 0, so we don't want different drugs wrapped up in the same era
|
||||||
|
AND coalesce(d.days_supply,0) >= 0 ---We have cases where days_supply is negative, and this can set the end_date before the start_date, which we don't want. So we're just looking over those rows. This is a data-quality issue.
|
||||||
|
)
|
||||||
|
|
||||||
|
, cteSubExposureEndDates (person_id, ingredient_concept_id, end_date) AS --- A preliminary sorting that groups all of the overlapping exposures into one exposure so that we don't double-count non-gap-days
|
||||||
|
(
|
||||||
/****
|
SELECT person_id, ingredient_concept_id, event_date AS end_date
|
||||||
DRUG ERA
|
FROM
|
||||||
Note: Eras derived from DRUG_EXPOSURE table, using 30d gap
|
(
|
||||||
****/
|
SELECT person_id, ingredient_concept_id, event_date, event_type,
|
||||||
IF OBJECT_ID('tempdb..#cteDrugTarget', 'U') IS NOT NULL
|
MAX(start_ordinal) OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
DROP TABLE #cteDrugTarget;
|
ORDER BY event_date, event_type ROWS unbounded preceding) AS start_ordinal,
|
||||||
|
-- this pulls the current START down from the prior rows so that the NULLs
|
||||||
/* / */
|
-- from the END DATES will contain a value we can compare with
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
-- Normalize DRUG_EXPOSURE_END_DATE to either the existing drug exposure end date, or add days supply, or add 1 day to the start date
|
ORDER BY event_date, event_type) AS overall_ord
|
||||||
SELECT d.DRUG_EXPOSURE_ID
|
-- this re-numbers the inner UNION so all rows are numbered ordered by the event date
|
||||||
,d.PERSON_ID
|
|
||||||
,c.CONCEPT_ID
|
|
||||||
,d.DRUG_TYPE_CONCEPT_ID
|
|
||||||
,DRUG_EXPOSURE_START_DATE
|
|
||||||
,COALESCE(DRUG_EXPOSURE_END_DATE, DATEADD(day, DAYS_SUPPLY, DRUG_EXPOSURE_START_DATE), DATEADD(day, 1, DRUG_EXPOSURE_START_DATE)) AS DRUG_EXPOSURE_END_DATE
|
|
||||||
,c.CONCEPT_ID AS INGREDIENT_CONCEPT_ID
|
|
||||||
INTO #cteDrugTarget
|
|
||||||
FROM @TARGET_CDMV5_SCHEMA.DRUG_EXPOSURE d
|
|
||||||
INNER JOIN @TARGET_CDMV5_SCHEMA.CONCEPT_ANCESTOR ca ON ca.DESCENDANT_CONCEPT_ID = d.DRUG_CONCEPT_ID
|
|
||||||
INNER JOIN @TARGET_CDMV5_SCHEMA.CONCEPT c ON ca.ANCESTOR_CONCEPT_ID = c.CONCEPT_ID
|
|
||||||
WHERE c.DOMAIN_ID = 'Drug'
|
|
||||||
AND c.CONCEPT_CLASS_ID = 'Ingredient'
|
|
||||||
AND c.STANDARD_CONCEPT = 'S';
|
|
||||||
|
|
||||||
/* / */
|
|
||||||
|
|
||||||
IF OBJECT_ID('tempdb..#cteEndDates', 'U') IS NOT NULL
|
|
||||||
DROP TABLE #cteEndDates;
|
|
||||||
|
|
||||||
/* / */
|
|
||||||
|
|
||||||
SELECT PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID
|
|
||||||
,DATEADD(day, - 30, EVENT_DATE) AS END_DATE -- unpad the end date
|
|
||||||
INTO #cteEndDates
|
|
||||||
FROM (
|
|
||||||
SELECT E1.PERSON_ID
|
|
||||||
,E1.INGREDIENT_CONCEPT_ID
|
|
||||||
,E1.EVENT_DATE
|
|
||||||
,COALESCE(E1.START_ORDINAL, MAX(E2.START_ORDINAL)) START_ORDINAL
|
|
||||||
,E1.OVERALL_ORD
|
|
||||||
FROM (
|
|
||||||
SELECT PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID
|
|
||||||
,EVENT_DATE
|
|
||||||
,EVENT_TYPE
|
|
||||||
,START_ORDINAL
|
|
||||||
,ROW_NUMBER() OVER (
|
|
||||||
PARTITION BY PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID ORDER BY EVENT_DATE
|
|
||||||
,EVENT_TYPE
|
|
||||||
) AS OVERALL_ORD -- this re-numbers the inner UNION so all rows are numbered ordered by the event date
|
|
||||||
FROM (
|
FROM (
|
||||||
-- select the start dates, assigning a row number to each
|
-- select the start dates, assigning a row number to each
|
||||||
SELECT PERSON_ID
|
SELECT person_id, ingredient_concept_id, drug_exposure_start_date AS event_date,
|
||||||
,INGREDIENT_CONCEPT_ID
|
-1 AS event_type,
|
||||||
,DRUG_EXPOSURE_START_DATE AS EVENT_DATE
|
ROW_NUMBER() OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
,0 AS EVENT_TYPE
|
ORDER BY drug_exposure_start_date) AS start_ordinal
|
||||||
,ROW_NUMBER() OVER (
|
FROM ctePreDrugTarget
|
||||||
PARTITION BY PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID ORDER BY DRUG_EXPOSURE_START_DATE
|
|
||||||
) AS START_ORDINAL
|
|
||||||
FROM #cteDrugTarget
|
|
||||||
|
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
||||||
-- add the end dates with NULL as the row number, padding the end dates by 30 to allow a grace period for overlapping ranges.
|
SELECT person_id, ingredient_concept_id, drug_exposure_end_date, 1 AS event_type, NULL
|
||||||
SELECT PERSON_ID
|
FROM ctePreDrugTarget
|
||||||
,INGREDIENT_CONCEPT_ID
|
|
||||||
,DATEADD(day, 30, DRUG_EXPOSURE_END_DATE)
|
|
||||||
,1 AS EVENT_TYPE
|
|
||||||
,NULL
|
|
||||||
FROM #cteDrugTarget
|
|
||||||
) RAWDATA
|
) RAWDATA
|
||||||
) E1
|
) e
|
||||||
INNER JOIN (
|
WHERE (2 * e.start_ordinal) - e.overall_ord = 0
|
||||||
SELECT PERSON_ID
|
)
|
||||||
,INGREDIENT_CONCEPT_ID
|
|
||||||
,DRUG_EXPOSURE_START_DATE AS EVENT_DATE
|
|
||||||
,ROW_NUMBER() OVER (
|
|
||||||
PARTITION BY PERSON_ID
|
|
||||||
,INGREDIENT_CONCEPT_ID ORDER BY DRUG_EXPOSURE_START_DATE
|
|
||||||
) AS START_ORDINAL
|
|
||||||
FROM #cteDrugTarget
|
|
||||||
) E2 ON E1.PERSON_ID = E2.PERSON_ID
|
|
||||||
AND E1.INGREDIENT_CONCEPT_ID = E2.INGREDIENT_CONCEPT_ID
|
|
||||||
AND E2.EVENT_DATE <= E1.EVENT_DATE
|
|
||||||
GROUP BY E1.PERSON_ID
|
|
||||||
,E1.INGREDIENT_CONCEPT_ID
|
|
||||||
,E1.EVENT_DATE
|
|
||||||
,E1.START_ORDINAL
|
|
||||||
,E1.OVERALL_ORD
|
|
||||||
) E
|
|
||||||
WHERE 2 * E.START_ORDINAL - E.OVERALL_ORD = 0;
|
|
||||||
|
|
||||||
/* / */
|
, cteDrugExposureEnds (person_id, drug_concept_id, drug_exposure_start_date, drug_sub_exposure_end_date) AS
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
dt.person_id
|
||||||
|
, dt.ingredient_concept_id
|
||||||
|
, dt.drug_exposure_start_date
|
||||||
|
, MIN(e.end_date) AS drug_sub_exposure_end_date
|
||||||
|
FROM ctePreDrugTarget dt
|
||||||
|
JOIN cteSubExposureEndDates e ON dt.person_id = e.person_id AND dt.ingredient_concept_id = e.ingredient_concept_id AND e.end_date >= dt.drug_exposure_start_date
|
||||||
|
GROUP BY
|
||||||
|
dt.drug_exposure_id
|
||||||
|
, dt.person_id
|
||||||
|
, dt.ingredient_concept_id
|
||||||
|
, dt.drug_exposure_start_date
|
||||||
|
)
|
||||||
|
--------------------------------------------------------------------------------------------------------------
|
||||||
|
, cteSubExposures(row_number, person_id, drug_concept_id, drug_sub_exposure_start_date, drug_sub_exposure_end_date, drug_exposure_count) AS
|
||||||
|
(
|
||||||
|
SELECT ROW_NUMBER() OVER (PARTITION BY person_id, drug_concept_id, drug_sub_exposure_end_date ORDER BY person_id)
|
||||||
|
, person_id, drug_concept_id, MIN(drug_exposure_start_date) AS drug_sub_exposure_start_date, drug_sub_exposure_end_date, COUNT(*) AS drug_exposure_count
|
||||||
|
FROM cteDrugExposureEnds
|
||||||
|
GROUP BY person_id, drug_concept_id, drug_sub_exposure_end_date
|
||||||
|
--ORDER BY person_id, drug_concept_id
|
||||||
|
)
|
||||||
|
--------------------------------------------------------------------------------------------------------------
|
||||||
|
/*Everything above grouped exposures into sub_exposures if there was overlap between exposures.
|
||||||
|
*So there was no persistence window. Now we can add the persistence window to calculate eras.
|
||||||
|
*/
|
||||||
|
--------------------------------------------------------------------------------------------------------------
|
||||||
|
, cteFinalTarget(row_number, person_id, ingredient_concept_id, drug_sub_exposure_start_date, drug_sub_exposure_end_date, drug_exposure_count, days_exposed) AS
|
||||||
|
(
|
||||||
|
SELECT row_number, person_id, drug_concept_id, drug_sub_exposure_start_date, drug_sub_exposure_end_date, drug_exposure_count
|
||||||
|
, datediff(day,drug_sub_exposure_start_date,drug_sub_exposure_end_date) AS days_exposed
|
||||||
|
FROM cteSubExposures
|
||||||
|
)
|
||||||
|
--------------------------------------------------------------------------------------------------------------
|
||||||
|
, cteEndDates (person_id, ingredient_concept_id, end_date) AS -- the magic
|
||||||
|
(
|
||||||
|
SELECT person_id, ingredient_concept_id, dateadd(day,-30,event_date) AS end_date -- unpad the end date
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT person_id, ingredient_concept_id, event_date, event_type,
|
||||||
|
MAX(start_ordinal) OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
|
ORDER BY event_date, event_type ROWS UNBOUNDED PRECEDING) AS start_ordinal,
|
||||||
|
-- this pulls the current START down from the prior rows so that the NULLs
|
||||||
|
-- from the END DATES will contain a value we can compare with
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
|
ORDER BY event_date, event_type) AS overall_ord
|
||||||
|
-- this re-numbers the inner UNION so all rows are numbered ordered by the event date
|
||||||
|
FROM (
|
||||||
|
-- select the start dates, assigning a row number to each
|
||||||
|
SELECT person_id, ingredient_concept_id, drug_sub_exposure_start_date AS event_date,
|
||||||
|
-1 AS event_type,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY person_id, ingredient_concept_id
|
||||||
|
ORDER BY drug_sub_exposure_start_date) AS start_ordinal
|
||||||
|
FROM cteFinalTarget
|
||||||
|
|
||||||
IF OBJECT_ID('tempdb..#cteDrugExpEnds', 'U') IS NOT NULL
|
UNION ALL
|
||||||
DROP TABLE #cteDrugExpEnds;
|
|
||||||
|
|
||||||
/* / */
|
-- pad the end dates by 30 to allow a grace period for overlapping ranges.
|
||||||
|
SELECT person_id, ingredient_concept_id, dateadd(day,30,drug_sub_exposure_end_date), 1 AS event_type, NULL
|
||||||
|
FROM cteFinalTarget
|
||||||
|
) RAWDATA
|
||||||
|
) e
|
||||||
|
WHERE (2 * e.start_ordinal) - e.overall_ord = 0
|
||||||
|
|
||||||
SELECT d.PERSON_ID
|
)
|
||||||
,d.INGREDIENT_CONCEPT_ID
|
, cteDrugEraEnds (person_id, drug_concept_id, drug_sub_exposure_start_date, drug_era_end_date, drug_exposure_count, days_exposed) AS
|
||||||
,d.DRUG_TYPE_CONCEPT_ID
|
(
|
||||||
,d.DRUG_EXPOSURE_START_DATE
|
SELECT
|
||||||
,MIN(e.END_DATE) AS ERA_END_DATE
|
ft.person_id
|
||||||
INTO #cteDrugExpEnds
|
, ft.ingredient_concept_id
|
||||||
FROM #cteDrugTarget d
|
, ft.drug_sub_exposure_start_date
|
||||||
INNER JOIN #cteEndDates e ON d.PERSON_ID = e.PERSON_ID
|
, MIN(e.end_date) AS era_end_date
|
||||||
AND d.INGREDIENT_CONCEPT_ID = e.INGREDIENT_CONCEPT_ID
|
, drug_exposure_count
|
||||||
AND e.END_DATE >= d.DRUG_EXPOSURE_START_DATE
|
, days_exposed
|
||||||
GROUP BY d.PERSON_ID
|
FROM cteFinalTarget ft
|
||||||
,d.INGREDIENT_CONCEPT_ID
|
JOIN cteEndDates e ON ft.person_id = e.person_id AND ft.ingredient_concept_id = e.ingredient_concept_id AND e.end_date >= ft.drug_sub_exposure_start_date
|
||||||
,d.DRUG_TYPE_CONCEPT_ID
|
GROUP BY
|
||||||
,d.DRUG_EXPOSURE_START_DATE;
|
ft.person_id
|
||||||
|
, ft.ingredient_concept_id
|
||||||
/* / */
|
, ft.drug_sub_exposure_start_date
|
||||||
|
, drug_exposure_count
|
||||||
INSERT INTO @TARGET_CDMV5_SCHEMA.drug_era
|
, days_exposed
|
||||||
SELECT row_number() OVER (
|
)
|
||||||
ORDER BY person_id
|
SELECT
|
||||||
) AS drug_era_id
|
row_number()over(order by person_id) drug_era_id
|
||||||
, person_id
|
, person_id
|
||||||
,INGREDIENT_CONCEPT_ID
|
, drug_concept_id
|
||||||
,min(DRUG_EXPOSURE_START_DATE) AS drug_era_start_date
|
, MIN(drug_sub_exposure_start_date) AS drug_era_start_date
|
||||||
,ERA_END_DATE
|
, drug_era_end_date
|
||||||
,COUNT(*) AS DRUG_EXPOSURE_COUNT
|
, SUM(drug_exposure_count) AS drug_exposure_count
|
||||||
,30 AS gap_days
|
, datediff(day,MIN(drug_sub_exposure_start_date),drug_era_end_date)-SUM(days_exposed) as gap_days
|
||||||
FROM #cteDrugExpEnds
|
INTO #tmp_de
|
||||||
GROUP BY person_id
|
FROM cteDrugEraEnds dee
|
||||||
,INGREDIENT_CONCEPT_ID
|
GROUP BY person_id, drug_concept_id, drug_era_end_date;
|
||||||
,drug_type_concept_id
|
|
||||||
,ERA_END_DATE;
|
|
||||||
|
|
||||||
|
INSERT INTO @cdm_schema.drug_era(drug_era_id,person_id, drug_concept_id, drug_era_start_date, drug_era_end_date, drug_exposure_count, gap_days)
|
||||||
|
SELECT * FROM #tmp_de;
|
||||||
```
|
```
|
||||||
|
|
||||||
## **Example ETL Script**
|
## **Example ETL Script**
|
||||||
|
|
Loading…
Reference in New Issue