确定SQL中事件的日期排序(对于每个组)

时间:2013-04-28 21:02:17

标签: sql sql-server-2008

我想确定SQL数据表中事件的顺序。我的数据被安排成使得每个标识符 - 日期 - 事件组合出现在单独的行上。输出应该是每个标识符的单行,指示发生3(并且仅3)个事件的顺序,以及指示三个事件中的哪个发生的标志。为了表明顺序,我只关心第一个事件的类型和最近事件的类型。 (所以,例如,ABC = ADAC,因为我只关心A是第一件事而C是最后一件事。)

假设我的数据是:

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'

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分: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对原始数据进行分组,其他所有内容都在此基础上完成。

对于SUB_Q中的每个ID,具有最小日期的CODE_GROUP,给出第一个事件以及具有最大日期的CODE_GROUP,给出最后一个事件。

对于SUB_Q中的每个ID,如果不是零,则三个CODE_GROUP中的任何一个的计数表明它在其生命周期中被设置为CODE_GROUP

SEE FIDDLE