Readmission of patient through 30 days after first discharge (total 31 days) - sql

I have below sample data in one of my table and I want to find "If the discharge is followed by a readmission through 30 days after first discharge (total 31 days), use the admit date from the first admission and the discharge date from the last discharge".
PatientId ClaimId Admit Date Discharge Date
A001 110001 12/20/2019 1/17/2020
A001 110002 4/30/2020 4/30/2020
A001 110003 4/18/2020 4/30/2020
A001 110004 5/1/2020 5/5/2020
A001 110005 5/8/2020 5/27/2020
A001 110006 8/22/2020 9/20/2020
A001 110007 9/2/2020 9/5/2020
A001 110008 9/21/2020 10/20/2020
A001 110009 10/21/2020 11/19/2020
A001 110010 9/2/2020 9/5/2020
I tried this way but I can get only min of admit date. Not sure how to find Max of discharge date through 30 days after first discharge. Appreciate help.
SELECT A.PatientId,
A.Discharge_Date,
Min(B.Admit_Date) AS MinOfadmitDate,
DATEDIFF(dd,A.Discharge_Date,Min(B.Admit_Date)) AS Day_span
FROM Table1 A
INNER JOIN Table1 AS B ON A.PatientId = B.PatientId
WHERE B.Admit_Date > A.Discharge_Date
GROUP BY A.PatientId, A.Discharge_Date
HAVING DATEDIFF(dd,A.Discharge_Date, Min(B.Admit_Date))<=30

Can any one help to find min of admit date and max of discharge date
through 30 days after first discharge?
I think you can use the analytical function to find the first discharge date and then use aggregate function to find min and max from 30 days as follows:
select t.patientid,
min(admit_date) as min_Admit_date,
max(discharge_date) as max_discharge_date
from (select t.*,
min(discharge_date) over (partition by patientid) as min_d_date
from your_table t) t
where dateadd(d,30,min_d_date) > admit_date

Related

Using WITH and UNION to compute number of flights and weather condition with two tables

Table A
date
flight
airport
2012-10-01
oneway
ATL, GA
2012-10-01
oneway
LAX, CA
2012-10-02
oneway
SAN, CA
2012-10-02
oneway
DTW, MI
2012-10-03
round
SFO, CA
2012-10-04
round
SFO, CA
2012-10-05
round
SFO, CA
Table B
date
temp
precip
2012-10-01
27
0.02
2012-10-02
35
0.00
2012-10-03
66
0.18
2012-10-04
57
0.00
2012-10-05
78
0.24
Table A has about 100k rows and whereas Table B has only about 60 rows
I am trying to query to find total number of flights on cold days and warm days as well as tracking the number of days for either cold or warm.
A cold day is defined when temp from Table B is below (<) 40 and warm otherwise.
In the real data, I have total 10 days that matches the date therefore I need to count for that when aggregating. I tried to get the total count without using CTE but I am keep getting wrong counts.
The expected outcome
Days
Num_of_flight
Num_of_days
cold day
4
2
warm day
3
3
You need a LEFT join of TableB to TableA and aggregation on the result of a CASE expression which returns 'cold' or 'warm':
SELECT CASE WHEN b.temp < 40 THEN 'cold day' ELSE 'warm day' END Days,
COUNT(*) Num_of_flight,
COUNT(DISTINCT a.date) Num_of_days
FROM TableB b LEFT JOIN TableA a
ON a.date = b.date
GROUP BY Days;
See the demo.

DAX Calculate sum of values

I have a table admissiontbl that records patients admissions.
Every patient has an AdmittedDate, DischargedDAte and LengthOfStay recorded.
PatientID
AdmittedDate
DischargedDate
AdYear
Admonth
LengthOfStay
001
02/01/2010
24/01/2010
2010
01
22
002
12/12/2009
18/12/2009
2009
12
7
003
12/12/2009
19/01/2010
2009
12
38
The LengthOfStay is calculated as DischargedDAte - AdmittedDate
Problem:
I will like to create a measure that sums up the LengthOfStay every month. This will include all patients discharged that month (i.e. including those admitted in the previous month or year).
For Example:
For Jan/2010, we want to calculate the SUM of LengthOfStay for ALL patients having their DischargedDate in Jan/2010. This must include patients having their AdmittedDate =< Jan/2010.
Scenario:
PatientID 003 was admitted on 12/12/2009 and discharged on 19/01/2010 will have his/her LengthOfStay = 38 days when you calculate for Jan/2010.
PatientID 002 was admitted on 12/12/2009 and discharged on 18/12/2009 will have his/her LengthOfStay = 7 days when you calculate for Jan/2010.
PatientID 001 was admitted on 02/01/2010 and discharged on 24/01/2010 will have his/her LengthOfStay = 22 days when you calculate for Jan/2010.
Result:
The SUM of LengthOfStay = 38 + 7 + 22 = 67 days
Note: The measure should take into account the month or year of the admission when calculating the SUM LengthOfStay.
I have tried the below DAX but it's not working
CM LOS Days =
Var CY = MAX(Admissions[Year])
Var CM = MAX(Admissions[Month])
Return
CALCULATE(SUM(Admissions[LengthOfStay]),Admissions[AdYear]= CY && Admissions[AdMonth]<=CM)
Grateful if anyone could help.

Calculate Churn by aggregating by date range in SQL

I am trying to calculate the churn rate from a data that has customer_id, group, date. The aggregation is going to be by id, group and date. The churn formula is (customers in previous cohort - customers in last cohort)/customers in previous cohort
customers in previous cohort refers to cohorts in before 28 days
customers in last cohort refers to cohorts in last 28 days
I am not sure how to aggregate them by date range to calculate the churn.
Here is sample data that I copied from SQL Group by Date Range:
Date Group Customer_id
2014-03-01 A 1
2014-04-02 A 2
2014-04-03 A 3
2014-05-04 A 3
2014-05-05 A 6
2015-08-06 A 1
2015-08-07 A 2
2014-08-29 XXXX 2
2014-08-09 XXXX 3
2014-08-10 BB 4
2014-08-11 CCC 3
2015-08-12 CCC 2
2015-03-13 CCC 3
2014-04-14 CCC 5
2014-04-19 CCC 4
2014-08-16 CCC 5
2014-08-17 CCC 3
2014-08-18 XXXX 2
2015-01-10 XXXX 3
2015-01-20 XXXX 4
2014-08-21 XXXX 5
2014-08-22 XXXX 2
2014-01-23 XXXX 3
2014-08-24 XXXX 2
2014-02-25 XXXX 3
2014-08-26 XXXX 2
2014-06-27 XXXX 4
2014-08-28 XXXX 1
2014-08-29 XXXX 1
2015-08-30 XXXX 2
2015-09-31 XXXX 3
The goal is to calculate the churn rate every 28 days in between 2014 and 2015 by the formula given above. So, it is going to be aggregating the data by rolling it by 28 days and calculating the churn by the formula.
Here is what I tried to aggregate the data by date range:
SELECT COUNT(distinct customer_id) AS count_ids, Group,
DATE_SUB(CAST(Date AS DATE), INTERVAL 56 DAY) AS Date_min,
DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY) AS Date_max
FROM churn_agg
GROUP BY count_ids, Group, Date_min, Date_max
Hope someone will help me with aggregation and churn calculation. I want to simply deduct the aggregated count_ids to deduct it from the next aggregated count_ids which is after 28 days. So this is going to be successive deduction of the same column value (count_ids). I am not sure if I have to use rolling window or simple aggregation to find the churn.
As corrected by #jarlh, it's not 2015-09-31 but 2015-09-30
You can use this to create 28 days calendar:
create table daysby28 (i int, _Date date);
insert into daysby28 (i, _Date)
SELECT i, cast('01-01-2014'as date) + i*INTERVAL '28 day'
from generate_series(0,50) i
order by 1;
After you use #jarlh churn_agg table creation he sent with the fiddle, with this query, you get what you want:
with cte as
(
select count(Customer) as TotalCustomer, Cohort, CohortDateStart From
(
select distinct a.Customer_id as Customer, b.i as Cohort, b._Date as CohortDateStart
from churn_agg a left join daysby28 b on a._Date >= b._Date and a._Date < b._Date + INTERVAL '28 day'
) a
group by Cohort, CohortDateStart
)
select a.CohortDateStart,
1.0*(b.TotalCustomer - a.TotalCustomer)/(1.0*b.TotalCustomer) as Churn from cte a
left join cte b on a.cohort > b.cohort
and not exists(select 1 from cte c where c.cohort > b.cohort and c.cohort < a.cohort)
order by 1
The fiddle of all together is here

Multiple day on day changes based on dates in data as not continuous

See table A. There are number of sales per date. The dates are not continuous.
I want table B where it gives the sales moves per the previous date in the dataset.
I am trying to do it in SQL but get stuck. I can do an individual day on day difference by entering the date but I want one where I don't need to enter the dates manually
A
Date Sales
01/01/2019 100
05/01/2019 200
12/01/2019 50
25/01/2019 25
31/01/2019 200
B
Date DOD Move
01/01/2019 -
05/01/2019 +100
12/01/2019 -150
25/01/2019 -25
31/01/2019 +175
Use lag():
select t.*,
(sales - lag(sales) over (order by date)) as dod_move
from t;

Summing Hours Worked Based On Two Unique Identifiers

I want to sum up the total hours worked in a given two week period (pay period) for employees in the company. I have a view that pulls a column for unique employee identifiers [CODE_USER], a column for uniquely identified pay types (Regular, Overtime, Holiday, Vacation, etc.) [Code], a column for total hours worked [Hours], and a column for each day of the workweek [Day].
As it stands right now, the [Hours] column shows total hours worked on a per day basis for each unique employee (based on the unique pay type, such as regular hours or overtime hours worked).
I need to combine all hours worked over a two week period for each employee [CODE_USER], for each pay type [CODE] into a summarized column named 'Hours'.
An ideal end result would look something like the following, given employee ID worked 80 regular hours, and 20 overtime hours over the course of two weeks (E1 equals Regular hours, E2 equals Overtime hours):
CODE_USER Code Hours
125 E1 80.00
125 E2 20.00
The closest I think I have gotten to solving it would be the following code, however it does not SUM hours worked for a unique CODE_USER for the two week period, it lists the hours worked for each day during the two week period as a collection of rows for that employee. For example, the following code shows 18 rows for the employee ID 125, the employee worked 10 full 8.00 hour days during the time period marked by E1 (regular), and there were 8 times where the employee worked overtime hours marked by E2 (overtime).
CODE:
SELECT [CODE_USER],
[Code],
SUM(Hours) AS Hours,
[Day]
FROM [LookUp].[dbo].[Daily_Hours_Worked]
WHERE [Day] >= '20191007' AND [Day] < '20191019'
AND [CODE_USER] LIKE '%125%'
GROUP BY [CODE_USER], [Code], [Hours], [Day]
ORDER BY [CODE_USER], [Day] DESC;
RESULTS:
CODE_USER Code Hours Day
125 E1 8.00 2019-10-18 00:00:00.000
125 E2 0.70 2019-10-18 00:00:00.000
125 E1 8.00 2019-10-17 00:00:00.000
125 E2 1.65 2019-10-17 00:00:00.000
125 E1 8.00 2019-10-16 00:00:00.000
125 E2 1.15 2019-10-16 00:00:00.000
125 E1 8.00 2019-10-15 00:00:00.000
125 E2 0.97 2019-10-15 00:00:00.000
125 E1 8.00 2019-10-14 00:00:00.000
125 E2 1.99 2019-10-14 00:00:00.000
125 E1 8.00 2019-10-11 00:00:00.000
125 E2 0.12 2019-10-11 00:00:00.000
125 E1 8.00 2019-10-10 00:00:00.000
125 E2 0.05 2019-10-10 00:00:00.000
125 E1 8.00 2019-10-09 00:00:00.000
125 E2 0.10 2019-10-09 00:00:00.000
125 E1 7.99 2019-10-08 00:00:00.000
125 E1 7.99 2019-10-07 00:00:00.000
EXPECTED RESULTS:
I want to see a SUM of E1, E2, etc., for the input pay period (2 week period) for each unique Employee ID [CODE_USER] in the table. The end result should be two rows for each employee with Regular Time (E1) and Overtime (E2) that SUMs that employee's hours worked for each category over the given time period.
Is it not simply that you should remove the day from the grouping and the specific employee from the where clause?
SELECT [CODE_USER],
[Code],
SUM(Hours) AS Hours
FROM [LookUp].[dbo].[Daily_Hours_Worked]
WHERE [Day] >= '20191007' AND [Day] < '20191019'
GROUP BY [CODE_USER], [Code]
ORDER BY [CODE_USER]
You don't need to group by hours; you're summing it. Situations where you should group by a column that you're also aggregating are rare
I'm confused as to why you say two weeks but the dates in your where clause are not two weeks apart; what if someone works on a weekend? I've left this part, just wanted to raise it as it seems odd that you'd do 12 days ie include only every other weekend (if the job is run once a fortnight)