I'm assuming CTE is the most efficient way to do this, but any suggestions would be great. I think I can do this in multiple steps a different way if I have to, but would love to make this as efficient as possible since the table is huge. I have a table like this:
PatientID | DischargeDate | RxDate | DaysSupply |
---|---|---|---|
1 | 1/1/2025 | 1/2/2025 | 3 |
2 | 1/3/2025 | 1/3/2025 | 5 |
3 | 1/3/2025 | 2/4/2025 | 10 |
I need to produce a table which keeps one line per patient discharge and creates 30 new columns indicating whether or not the patient had an antibiotic that day, like this:
PatientID | DischargeDate | RxDate | DaysSupply | Day1 | Day2 | Day3 | Day4 and so on |
---|---|---|---|---|---|---|---|
1 | 1/1/2025 | 1/2/2025 | 3 | 1 | 1 | 1 | 0 |
However, for the purposes of this post, I'll certainly settle for a solution that produces the following and then I can transpose it. Note - I am only keeping the records in which a patient started a prescription within 1-30 days post discharge. So you'll notice I left out patient #3 below.
PatientID | DischargeDate | RxDate |
---|---|---|
1 | 1/1/2025 | 1/2/2025 |
1 | 1/1/2025 | 1/3/2025 |
1 | 1/1/2025 | 1/4/2025 |
2 | 1/3/2025 | 1/3/2025 |
2 | 1/3/2025 | 1/4/2025 |
2 | 1/3/2025 | 1/5/2025 |
2 | 1/3/2025 | 1/6/2025 |
2 | 1/3/2025 | 1/7/2025 |
Any suggestions are greatly appreciated. Thank you!
For the first option, the best way (if not very concise) is to just use a bunch of CASE
expressions.
SELECT
p.PatientID,
p.DischargeDate,
p.RxDate,
p.DaysSupply,
CASE WHEN p.DaysSupply >= 01 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day01,
CASE WHEN p.DaysSupply >= 02 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day02,
CASE WHEN p.DaysSupply >= 03 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day03,
CASE WHEN p.DaysSupply >= 04 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day04,
CASE WHEN p.DaysSupply >= 05 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day05,
CASE WHEN p.DaysSupply >= 06 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day06,
CASE WHEN p.DaysSupply >= 07 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day07,
CASE WHEN p.DaysSupply >= 08 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day08,
CASE WHEN p.DaysSupply >= 09 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day09,
CASE WHEN p.DaysSupply >= 10 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day10,
CASE WHEN p.DaysSupply >= 11 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day11,
CASE WHEN p.DaysSupply >= 12 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day12,
CASE WHEN p.DaysSupply >= 13 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day13,
CASE WHEN p.DaysSupply >= 14 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day14,
CASE WHEN p.DaysSupply >= 15 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day15,
CASE WHEN p.DaysSupply >= 16 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day16,
CASE WHEN p.DaysSupply >= 17 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day17,
CASE WHEN p.DaysSupply >= 18 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day18,
CASE WHEN p.DaysSupply >= 19 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day19,
CASE WHEN p.DaysSupply >= 20 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day20,
CASE WHEN p.DaysSupply >= 21 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day21,
CASE WHEN p.DaysSupply >= 22 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day22,
CASE WHEN p.DaysSupply >= 23 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day23,
CASE WHEN p.DaysSupply >= 24 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day24,
CASE WHEN p.DaysSupply >= 25 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day25,
CASE WHEN p.DaysSupply >= 26 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day26,
CASE WHEN p.DaysSupply >= 27 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day27,
CASE WHEN p.DaysSupply >= 28 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day28,
CASE WHEN p.DaysSupply >= 29 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day29,
CASE WHEN p.DaysSupply >= 30 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS Day30
FROM Patient p
WHERE DATEADD(day, 30, p.DischargeDate) > p.RxDate;
For the second option you can use GENERATE_SERIES
to dynamically generate more rows, and some date math.
SELECT
p.PatientID,
p.DischargeDate,
DATEADD(day, g.value, p.RxDate) AS RxDate
FROM Patient p
CROSS APPLY GENERATE_SERIES(0, p.DaysSupply - 1) g
WHERE DATEADD(day, 30, p.DischargeDate) > p.RxDate;