2013-04-28 1 views
2

Я хотел бы определить порядок событий в таблице данных SQL. Мои данные устроены так, что каждая комбинация идентификатор-дата-событие появляется в отдельной строке. Вывод должен быть одной строкой для каждого идентификатора, указывая порядок, в котором произошло 3 (и только 3) события, и флаг, указывающий, какое из трех событий когда-либо происходило. Чтобы указать порядок, мне нужно знать только тип первого события и тип последнего события. (Так, например, ABC = ADAC, потому что я заинтересован только в том, что А было самое первое и C была самая последняя вещь.)Определить порядок событий в SQL (для каждой группы)

Пусть мои данные:

CREATE TABLE #ABC 
(ID INT NOT NULL, 
CODE_DATE DATE NOT NULL, 
CODE_GROUP VARCHAR(10) NULL) 

INSERT INTO #ABC VALUES (1,'20000-01-01','APPROVED') 
INSERT INTO #ABC VALUES (1,'20001-01-01','DENIED') 
INSERT INTO #ABC VALUES (1,'20003-01-01','ON HOLD') 
INSERT INTO #ABC VALUES (1,'20002-01-01','APPROVED') 
INSERT INTO #ABC VALUES (2,'20008-01-01','DENIED') 
INSERT INTO #ABC VALUES (2,'20004-01-01','DENIED') 
INSERT INTO #ABC VALUES (3,'20006-01-01','ON HOLD') 
INSERT INTO #ABC VALUES (3,'20005-01-01','APPROVED') 
INSERT INTO #ABC VALUES (3,'20009-01-01','DENIED') 
INSERT INTO #ABC VALUES (4,'20001-01-01','ON HOLD') 
INSERT INTO #ABC VALUES (4,'20004-01-01','ON HOLD') 
INSERT INTO #ABC VALUES (4,'20007-01-01','DENIED') 
INSERT INTO #ABC VALUES (5,'20005-01-01','ON HOLD') 
INSERT INTO #ABC VALUES (5,'20008-01-01','ON HOLD') 
INSERT INTO #ABC VALUES (5,'20009-01-01','APPROVED') 

Тогда искомый результат:

ID RESULT     EVER_APPROVED EVER_DENIED EVER_ON_HOLD 
1 'APPROVED THEN ON HOLD' 'Y'    'Y'   'Y' 
2 'DENIED'    'N'    'Y'   'N' 
3 'APPROVED THEN DENIED' 'Y'    'Y'   'Y' 
4 'ON HOLD THEN DENIED' 'N'    'Y'   'Y' 
5 'ON HOLD THEN APPROVED' 'Y'    'N'   'Y' 
+0

попробовал что-нибудь или ..? – jurgenreza

+0

Я действительно застрял. Обычно я использую шаг данных SAS, но больше не имею доступа к SAS. Я бы предположил, что могу использовать MIN и MAX в полях даты, чтобы идентифицировать первые последние события на ID, но я не уверен. – user1126915

ответ

1

Это дает правильные результаты для ваших данных:

with ABCOrdered as 
(
    select * 
    , FirstEvent = row_number() over (partition by ID order by CODE_DATE) 
    , LastEvent = row_number() over (partition by ID order by CODE_DATE desc) 
    from ABC 
) 
select f.ID 
    , [RESULT] = case 
    when f.CODE_GROUP = l.CODE_GROUP or l.CODE_GROUP is null then f.CODE_GROUP 
    else f.CODE_GROUP + ' THEN ' + l.CODE_GROUP 
    end 
    , EVER_APPROVED = case 
    when exists (select 1 from ABC where l.ID = ABC.ID and ABC.CODE_GROUP = 'APPROVED') then 'Y' 
    else 'N' 
    end 
    , EVER_DENIED = case 
    when exists (select 1 from ABC where l.ID = ABC.ID and ABC.CODE_GROUP = 'DENIED') then 'Y' 
    else 'N' 
    end 
    , EVER_ON_HOLD = case 
    when exists (select 1 from ABC where l.ID = ABC.ID and ABC.CODE_GROUP = 'ON HOLD') then 'Y' 
    else 'N' 
    end 
from ABCOrdered f 
    left join ABCOrdered l on f.ID = l.ID and l.LastEvent = 1 
where f.FirstEvent = 1 
order by f.ID 

SQL Fiddle with demo.

+0

Спасибо! Это работает по моим данным. – user1126915

0

QUERY:

SELECT 
    ID, 
    (SELECT CODE_GROUP FROM ABC WHERE ID = SUB_Q.ID AND CODE_DATE = SUB_Q.MIN_DATE) AS FIRST_EVENT, 
    (SELECT CODE_GROUP FROM ABC WHERE ID = SUB_Q.ID AND CODE_DATE = SUB_Q.MAX_DATE) AS LAST_EVENT, 
    EVER_APPROVED = CASE WHEN (SELECT COUNT(*) FROM ABC WHERE ID = SUB_Q.ID AND CODE_GROUP = 'APPROVED') = 0 THEN 'N' ELSE 'Y' END, 
    EVER_DENIED = CASE WHEN (SELECT COUNT(*) FROM ABC WHERE ID = SUB_Q.ID AND CODE_GROUP = 'DENIED') = 0 THEN 'N' ELSE 'Y' END, 
    EVER_ONHOLD = CASE WHEN (SELECT COUNT(*) FROM ABC WHERE ID = SUB_Q.ID AND CODE_GROUP = 'ON HOLD') = 0 THEN 'N' ELSE 'Y' END 
FROM 
    (SELECT 
    ID, 
    MIN(CODE_DATE) AS MIN_DATE, 
    MAX(CODE_DATE) AS MAX_DATE 
    FROM 
    ABC 
    GROUP BY 
    ID) AS SUB_Q 

РЕЗУЛЬТАТ:

ID FIRST_EVENT LAST_EVENT EVER_APPROVED EVER_DENIED EVER_ONHOLD 
1 APPROVED ON HOLD  Y    Y   Y 
2 DENIED  DENIED  N    Y   N 
3 APPROVED DENIED  Y    Y   Y 
4 ON HOLD  DENIED  N    Y   Y 
5 ON HOLD  APPROVED Y    N   Y 

ОБЪЯСНЕНИЕ:

Во-первых, у меня есть простой суб запрос называется SUB_Q, что группы исходных данных, по ID, и все остальное делается на p этого.

Для каждого идентификатора в SUB_Q, CODE_GROUP того, у кого есть дата минус, выдает первое событие и CODE_GROUP из числа с максимальной датой, дает последнее событие.

Для каждого идентификатора в SUB_Q, подсчет любого из трех CODE_GROUP s, если не равен нулю, показывает, что он всегда был установлен на CODE_GROUP в течение его жизненного цикла.

SEE FIDDLE

1

Вот еще один способ сделать это:

;WITH cteMaxMin As 
(
    SELECT 
     ID, 
     Max(CODE_DATE+':'+CODE_GROUP) As MaxDt, 
     Min(CODE_DATE+':'+CODE_GROUP) As MinDt, 
     Max(Case When CODE_GROUP='APPROVED' Then 'Y' Else Null End) As Apd, 
     Max(Case When CODE_GROUP='DENIED' Then 'Y' Else Null End) As Dnd, 
     Max(Case When CODE_GROUP='ON HOLD' Then 'Y' Else Null End) As Ohd 
    FROM  #ABC 
    GROUP BY ID 
) 
SELECT 
    ID, 
    SUBSTRING(MaxDt, 13, LEN(MaxDt)) 
    + COALESCE(' THEN '+SUBSTRING(MinDt, 13, LEN(MinDt)), '') As RESULT, 
    COALESCE(Apd, 'N')    As EVER_APPROVED, 
    COALESCE(Dnd, 'N')    As EVER_DENIED, 
    COALESCE(Ohd, 'N')    As EVER_ON_HOLD 
FROM cteMaxMin 
Смежные вопросы