2016-09-21 4 views
5

Я пытаюсь группировать даты в течение 3 дней друг от друга и назначать баллы на основе реадмиссии в течение 30 дней. MRN получит 3 балла за повторный прием. Любая помощь по изменению моего запроса ниже будет отличной.SQL: пробелы и острова, сгруппированные даты

Пример:

CREATE TABLE #z  (
    ID INT IDENTITY(1,1), 
    OrganizationMrn INT, 
    VisitDate DATE, 
    CATEGORY VARCHAR(15)) 

INSERT #z(OrganizationMrn, VisitDate, CATEGORY) 
VALUES 
(1, '1/2/2016','Inpatient'), 
(1, '1/5/2016','Inpatient'), 
(1, '1/7/2016','Inpatient'), 
(1, '1/8/2016','Inpatient'), 
(1, '1/9/2016','Inpatient'), 
(1, '2/4/2016','Inpatient'), 
(1, '6/2/2016','Inpatient'), 
(1, '6/3/2016','Inpatient'), 
(1, '6/5/2016','Inpatient'), 
(1, '6/6/2016','Inpatient'), 
(1, '6/8/2016','Inpatient'), 
(1, '7/1/2016','Inpatient'), 
(1, '8/1/2016','Inpatient'), 
(1, '8/4/2016','Inpatient'), 
(1, '8/15/2016','Inpatient'), 
(1, '8/18/2016','Inpatient'), 
(1, '8/28/2016','Inpatient'), 
(1, '10/12/2016','Inpatient'), 
(1, '10/15/2016','Inpatient'), 
(1, '11/17/2016','Inpatient'), 
(1, '12/20/2016','Inpatient') 

Желаемая Выход: Я действительно только нужно Фактические Визиты, OrganizationMrn и очки. (Когда даты сгруппированы (Фактические визиты), первая дата должна использоваться для реадмиссии в течение 30 дней).

ACTUAL Visits Grouped Dates    Re-admissions  Points 
1/2/2016  (grouped 1/2, 1/5) 
1/7/2016  (grouped 1/7, 1/8, 1/9)  Readmit from 1/2 (3 points) 
2/4/2016         Readmit from 1/7 (3 points) 
6/2/2016  (grouped 6/2, 6/3, 6/5) 
6/6/2016  (grouped 6/6, 6/8)   Readmit from 6/2 (3 points) 
7/1/2016         Readmit from 6/6 (3 points) 
8/1/2016  (grouped 8/1, 8/4) 
8/15/2016  (grouped 8/15, 8/18)  Readmit from 8/1 (3 points) 
8/28/2016         Readmit from 8/15 (3 points) 
10/12/2016  (grouped 10/12, 10/15) 
11/17/2016 
12/20/2016 
___________________________________________ 6 total readmits (18 total points) 

В нижеследующем запросе используются промежутки и острова для группировки дней в течение 3 дней друг от друга. Однако, если даты являются последовательными, даты начала и окончания группируются. (Пример: запрос ниже групп, [1/2, 1/5, 1/7 /, 1/8, 1/9] в одну строку; даты должны быть разделены на две строки [1/2, 1/5] и [1/7 /, 1/8, 1/9]).

Как только у сгруппированных дат есть отдельные строки, мне нужно назначить 3 балла для каждого повторного приема в течение 30 дней. (Фактический визит на организацию в течение 30 дней друг с другом). Вышеупомянутый раздел вывода описывает, как должны быть сгруппированы даты в моем примере.

;WITH StartingPoints AS (
    SELECT OrganizationMrn, VisitDate, ROW_NUMBER() OVER (ORDER BY VisitDate) AS Sequence FROM #z AS A 
    WHERE a.category = 'Inpatient' AND NOT EXISTS (
     SELECT * FROM #z AS B 
     WHERE B.OrganizationMrn = A.OrganizationMrn AND 
       B.VisitDate >= DATEADD(DAY, -4, A.VisitDate) AND 
       B.VisitDate < A.VisitDate AND 
       B.Category = 'Inpatient' ) ), 
EndingPoints AS (
    SELECT OrganizationMrn, VisitDate, ROW_NUMBER() OVER (ORDER BY VisitDate) AS Sequence FROM #z AS A 
    WHERE a.category = 'Inpatient' AND NOT EXISTS (
     SELECT * FROM #z AS B 
     WHERE B.OrganizationMrn = A.OrganizationMrn AND 
       B.VisitDate <= DATEADD(DAY, 4, A.VisitDate) AND 
       B.VisitDate > A.VisitDate AND 
       B.Category = 'Inpatient' ) ) 
SELECT S.OrganizationMrn, S.VisitDate AS StartDate, E.VisitDate AS EndDate, CEILING((DATEDIFF(DAY, S.VisitDate, E.VisitDate) + 1)/4.0) AS Points 
FROM StartingPoints AS S 
    JOIN EndingPoints AS E ON (E.Sequence = S.Sequence) 
ORDER BY S.OrganizationMrn DESC 
+1

Почему нет 1/5 сгруппированы по 1/7? –

+0

или 6/5 с 6/6? –

+0

1/5 не сгруппировано с 1/7, потому что 1/2 является фактическим посещением на 1/5 (первое свидание в группе - это фактическая дата посещения). 1/7 не в течение 3 дней с 1/2, так что 1/7 будет новым визитом. Имеет ли это смысл? – JBritton

ответ

2

Этот ответ работает на примере, который вы предоставили. Это может быть полезно, если у вас есть небольшие столы и ограниченный доступ. (Он использует рекурсию в датах).

WITH a AS (
    SELECT 
     z1.VisitDate 
     , z1.OrganizationMrn 
     , (SELECT MIN(VisitDate) FROM #z WHERE VisitDate > DATEADD(day, 3, z1.VisitDate)) AS NextDay 
    FROM 
     #z z1 
    WHERE 
     CATEGORY = 'Inpatient' 
), a1 AS ( 
    SELECT 
     OrganizationMrn 
     , MIN(VisitDate) AS VisitDate 
     , MIN(NextDay) AS NextDay 
    FROM 
     a 
    GROUP BY 
     OrganizationMrn 
), b AS (
    SELECT 
     VisitDate 
     , OrganizationMrn 
     , NextDay 
     , 1 AS OrderRow 
    FROM 
     a1 


    UNION ALL 

    SELECT 
     a.VisitDate 
     , a.OrganizationMrn 
     , a.NextDay 
     , b.OrderRow +1 AS OrderRow 
    FROM 
     a 
     JOIN b 
     ON a.VisitDate = b.NextDay 
), c AS (
SELECT 
    VisitDate 
    , (SELECT MAX(VisitDate) FROM b WHERE b1.VisitDate > VisitDate) AS PreviousVisitDate 
FROM 
    b b1 
) 
SELECT 
    c1.VisitDate 
    , CASE 
     WHEN DATEDIFF(day,c1.PreviousVisitDate,c1.VisitDate) < 30 THEN PreviousVisitDate 
     ELSE NULL 
    END AS ReAdmissionFrom 
    , CASE 
     WHEN DATEDIFF(day,c1.PreviousVisitDate,c1.VisitDate) < 30 THEN 3 
     ELSE 0 
    END AS Points 
FROM 
    c c1