2010-01-29 4 views
2

에서 각 레코드에 대해 경과 일 DATEDIFF 얻기 :SQL 질문 :이 테이블을 감안할 때 그룹

alt text

가 어떻게 ID_NUMBER의 각 그룹에 대해 각 status_date 사이의 일에 DATEDIFF를받을 수 있나요? 즉, ID_Number가 주어진 각 상태의 경과 일 수를 찾아야합니다. 각각에 대해

  • 가있는 상태가 될 것입니다 ID_NUMBER

    • 모든 ID_NUMBER 각 ID_NUMBER에 대한 빠른 날짜 있어야 할 received_date이있을 것이다 (그러나 응용 프로그램은 적용하지 않습니다) :

      어떤 것들은

      는 알고 해당 status_date는 ID_Number가 특정 상태에 주어진 날짜입니다.
    • 는 상태 열은 항상 반드시
    • 모든 ID_NUMBER 최신 날짜 있어야 할 closed_date을해야합니다 (응용 프로그램은 적용하지 않습니다) 같은 순서로 모든 시간을 가지 않습니다 (하지만 응용 프로그램은 적용하지 않습니다)

    샘플 출력 : 따라서 ID_Number 2001의 첫 번째 날짜 (received_date)는 2009-05-02이며 다음에 만나는 날짜는 'open'상태이며 2009-05-02이므로 경과 일수는 0입니다. 발생한 다음 날짜로 이동하는 것은 '투자'상태의 2009-05-10이며 경과 일수는 이전 날짜부터 8입니다. 발생한 다음 날짜는 2009-07-11이며 경과 일수는 이전 날짜로부터 62입니다.

    편집 추가 할 :

    이 경과 일이 테이블/뷰에 컬럼으로 끝이 할 수 있습니까? 나는이 일부 샘플 출력이 정말 도움이 될 2000

  • +0

    필자는 원본 테이블을 새로운 날짜 열로 복제하기 위해 모든 대답을 추가했습니다. closed_date가없는 경우는 null입니다. –

    답변

    0

    SQL 서버 것을 추가하는 것을 잊었다, 그러나 이것은 각 ID_NUMBER/상태 조합에 대한 정보 원하는 가정, 당신이 무엇을 의미하는지에 추측 :

    select ID_Number, Status, EndDate - StartDate as DaysElapsed 
    from (
        select ID_Number, Status, min(coalesce(received_date, status_date)) as StartDate, max(coalesce(closed_date, status_date)) as EndDate 
        from Table1 
        group by ID_Number, Status 
    ) a 
    
    1

    내가 이해하는 것은 closed_date까지 동일한 id에 대해 첫 번째 status_date와 다음 status_date 사이의 차이가 필요하다는 것입니다.

    이것은 SQL 2005 이상에서만 작동합니다.

    ;with test as (
        select 
         key, 
         id_number, 
         status, 
         received_date, 
         status_date, 
         closed_date, 
         row_number() over (partition by id order by status_date, key) as rownum 
        from @test 
        ) 
    select 
        t1.key, 
        t1.id_number, 
        t1.status, 
        t1.status_date, 
        t1.received_date, 
        t1.closed_date, 
        datediff(d, case when t1.rownum = 1 
           then t1.received_date 
           else  
            case when t2.status_date is null 
             then t1.closed_date 
             else t2.status_date 
            end 
          end, 
          t1.status_date 
         ) as days 
    from test t1 
    left outer join test t2 
    on t1.id = t2.id 
        and t2.rownum = t1.rownum - 1 
    

    이 솔루션은 SQL 2000에서 작동하지만 수행하는 방법을 잘 모르겠습니다 :

    select *, 
        datediff(d, 
         case when prev_date is null 
          then closed_date 
          else prev_date 
         end, 
         status_date) 
    from ( 
        select *, 
         isnull((select top 1 t2.status_date 
          from @test t2 
          where t1.id_number = t2.id_number 
          and t2.status_date < t1.status_date 
          order by t2.status_date desc 
         ),received_date) as prev_date 
        from @test t1 
    ) a 
    order by id_number, status_date 
    

    : 테이블의 이름으로 @Test 테이블을 교체합니다.

    +0

    질문에 추가 한 샘플 결과를 기반으로 결과를 수정했습니다. –

    +0

    어. 이것은 원래 게시물에 추가하는 것을 잊어 버린 정보 인 sql2000에서 구현하는 것이 꽤 추한 것처럼 보입니다. – GregD

    +0

    @GregD : 각 ID_Number에 대해 KEY 열이 항상 연속적으로 표시됩니까? –

    0

    까다로운 비트는 이전 상태를 판별하여 현재 상태와 동일한 행에 두는 것입니다. KeyStatusDate 사이에 상관 관계가있는 경우 (즉, Key(x) > Key(y)은 항상 StatusDate(x) >= StatusDate(y)을 의미 함) 약간 단순화됩니다. 불행히도 그럴 것 같지 않습니다.

    추 신 : Key은 테이블의 고유 식별자라고 가정합니다. 당신은 다른 것을 나타 내기 위해 아무 것도 말하지 않았습니다. 당신이 기초로이 일단

    SELECT Key, 
         ID_Number, 
         (
         SELECT TOP 1 Key 
         FROM StatusUpdates prev 
         WHERE (prev.ID_Number = cur.ID_Number) 
          AND ( (prev.StatusDate < cur.StatusDate) 
           OR ( prev.StatusDate = cur.StatusDate 
            AND prev.Key < cur.Key 
            ) 
           ) 
         ORDER BY StatusDate, Key /*Consider index on (ID_Number, StatusDate, Key)*/ 
         ) PrevKey 
    FROM StatusUpdates cur 
    

    , 당신이 현재 또는 이전 StatusUpdate에서 필요로하는 다른 정보를 추정하는 것은 쉽다. 예 :

    SELECT c.*, 
         p.Status AS PrevStatus, 
         p.StatusDate AS PrevStatusDate, 
         DATEDIFF(d, c.StatusDate, p.StatusDate) AS DaysElapsed 
    FROM (
         SELECT Key, 
           ID_Number, 
           Status, 
           SattusDate, 
           (
           SELECT TOP 1 Key 
           FROM StatusUpdates prev 
           WHERE (prev.ID_Number = cur.ID_Number) 
            AND ( (prev.StatusDate < cur.StatusDate) 
             OR ( prev.StatusDate = cur.StatusDate 
              AND prev.Key < cur.Key 
              ) 
             ) 
           ORDER BY StatusDate, Key 
           ) PrevKey 
         FROM StatusUpdates cur 
         ) c 
         JOIN StatusUpdates p ON 
          p.Key = c.PrevKey