2010-01-29 92 views
2

在經過的每個記錄天:SQL問題:獲取DATEDIFF在對於這個表的一組

alt text

我如何獲得各組ID_NUMBER的每個status_date之間的天DATEDIFF?換句話說,我需要找出已經給出ID_Number的每個狀態的經過天數。

有些事情知道:

  • 所有ID_NUMBER會有這應該是每個ID_NUMBER的最早日期received_date(但應用不強制)
  • 對於每個ID_NUMBER會有一個狀態相應的status_date是ID_Number被賦予該特定狀態的日期。
  • 狀態欄並不一定總是以相同的順序,每次去(應用程序不執行)
  • 所有ID_NUMBER會有這應該是最新的日期closed_date(但應用不強制)

樣本輸出: 因此,對於ID_Number 2001,第一個日期(received_date)是2009-05-02,並且您遇到的下一個日期的狀態爲「打開」,並且是2009-05-02,因此過去的日期爲0轉到下一個遇到的日期是2009-05-10,狀態爲「投資」,過去的日期是從前一天開始的8天。遇到的下一個日期是2009年7月11日,經過的日期是從前一日期算起的62天。

編輯補充:

是否有可能有經過幾天結束了作爲此表/視圖中的列? 我還忘了補充一點,這是SQL Server 2000中

+0

我添加了所有列到我的答案複製原始表與一個新的天列。當沒有closed_date時它是空的。 – 2010-01-30 00:25:17

回答

0

一些樣本輸出將真正幫助,但是這是在你的意思猜測,假設你想要的信息,每個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

我的理解是,您需要第一個status_date和下一個status_date之間的差異,以獲得相同的ID等等,直到closed_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

我根據您添加到問題中的示例輸出修改了結果。 – 2010-01-30 00:47:07

+0

呃。看起來這將是相當醜陋的在sql2000中實現,這是我忘了添加到我的原始文章的信息。 – GregD 2010-02-01 16:53:53

+0

@GregD:對於每個ID_Number,KEY列是否總是連續的? – 2010-02-01 17:25:07

0

棘手的是確定以前的狀態,並把它放在與當前狀態相同的行。如果在KeyStatusDate之間存在相關性(即,Key(x) > Key(y)總是暗示StatusDate(x) >= StatusDate(y)),那麼它將被簡化一點。不幸的是,似乎並非如此。PS:我假設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