2013-04-25 104 views
0

我有一個持有狀態更新的平坦表。SQL數據庫日期範圍

這些更新存儲在以下格式:

AGREEMENTID | StatusID | StatusDate

源數據:

AgreementID StatusID StatusDate 
109   1   14/01/2013 15:00:33 
109   2   14/01/2013 15:01:28 
109   2   14/01/2013 15:01:28 
109   2   14/01/2013 15:02:42 
109   2   26/02/2013 16:27:38 
109   2   26/02/2013 16:27:45 
109   8   19/02/2013 13:57:33 
109   8   04/03/2013 16:46:29 
109   8   18/03/2013 14:08:12 
109   8   18/03/2013 14:47:00 
109   8   18/03/2013 14:48:46 
109   9   26/03/2013 15:41:51 

我所需要的就是映射在日期範圍的協議狀態,一個協議可以有相同的StatusID的多個狀態更新,而一旦協議進入到下一個StatusID它不能退回到以前的狀態ID。

對於上一個狀態,日期範圍應該是StatusDate To Date。

我有下面一段代碼,但結果不給我我想要的東西......

SELECT  
    AgreementID, 
    CONVERT(datetime, CONVERT(varchar(10), StatusDate, 103), 103) AS StatusDate, 
    CONVERT(datetime, CONVERT(varchar(10), StatusDate, 103), 103) AS DateFrom, 
    CASE WHEN DateTo IS NULL THEN CONVERT(datetime, CONVERT(varchar(10), GETDATE(), 103), 103) ELSE CONVERT(datetime, CONVERT(varchar(10), DateTo, 103), 103) END AS DateTo, 
    StatusID 
FROM   
    (
    SELECT  
     AgreementID, 
     StatusID, 
     StatusDate, 
     (SELECT TOP (1) StatusDate FROM TblStatusUpdates AS SU WHERE SU.AgreementID = U.AgreementID AND SU.StatusDate > U.StatusDate ORDER BY StatusID, StatusDate ASC) DateTo, 
     RN = ROW_NUMBER() OVER (Partition BY AgreementID ORDER BY StatusDate) 
    FROM   
     (
     SELECT  
      AgreementID, 
      StatusID, 
      MIN(StatusDate) AS StatusDate 
     FROM   
      TblStatusUpdates 
     GROUP BY 
      AgreementID, StatusID 
     ) AS U 
    ) AS A 

下面是該查詢的結果舉例:

AgreementID StatusDate DateFrom DateTo  StatusID 
109   14/01/2013 14/01/2013 14/01/2013 1 
109   14/01/2013 14/01/2013 14/01/2013 2 
109   19/02/2013 19/02/2013 26/02/2013 8 
109   26/03/2013 26/03/2013 25/04/2013 9 

由於你可以看到,日期到價值是不正確的,它應該總是運行到下一個狀態ID的前一天。

因此,在這個例子中,然後狀態2應從19/02/2013運行,以18/02/13

任何建議將是巨大的。謝謝。

+2

只是一個快速的評論:[STOP DECLARING VARCHAR無長](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring-varchar-without- length.aspx)。這是懶惰和有問題的。 – 2013-04-25 15:52:57

+0

它在哪裏聲明沒有長度? – 2013-04-25 15:58:29

+0

'CONVERT(varchar,'all over the place。'varchar(WHAT?)'? – 2013-04-25 15:59:47

回答

0

如果您使用的是SQL Server 2012中,你可以這樣做:

with agst as 
    (select AgreementID, 
      CONVERT(datetime, CONVERT(varchar(10), min(StatusDate), 103), 103) AS StatusDate, 
      CONVERT(datetime, CONVERT(varchar(10), min(StatusDate), 103), 103) AS DateFrom, 
      StatusID 
     from TblStatusUpdates 
     group by AgreementID, StatusID 
    ) 
select agst.*, 
     lead(datefrom) over (partition by AgreementId, statusId order by DateFrom) - 1 as DateTo 
from agst 

我想我只要使用聚合,這是agst共表表達式簡化了StatusDate /爲MinDate的計算。 lead()函數只是將下一個值拉入該行。

你可以用相關的子查詢做類似的事情。這是該版本:

with agst as 
    (select AgreementID, 
      CONVERT(datetime, CONVERT(varchar(10), min(StatusDate), 103), 103) AS StatusDate, 
      CONVERT(datetime, CONVERT(varchar(10), max(StatusDate), 103), 103) AS DateFrom, 
      StatusID 
     from TblStatusUpdates 
     group by AgreementID, StatusID 
    ) 
select agst.*, 
     (select top 1 DateFrom 
     from agst agst2 
     where agst2.agreementId = agst.agreementid and 
       agst2.StatusID = agst.StatusID and 
       agst2.DateFrom > agst.DateFrom 
     order by DateFrom desc 
     ) - 1 as DateTo 
from agst 
+0

對不起,我應該說我是使用2008 – 2013-04-25 16:13:35

+0

@Richard ......我懷疑是那麼多,w這就是爲什麼我包含這兩個版本。 – 2013-04-25 16:14:50

+0

你用代碼'agst2.id = agst.id'稍微鬆了一點我是否應該是StatusID? – 2013-04-25 16:19:08

-1

希望這是你在找什麼。

SQL FIDDLE

+0

嗨。感謝那。它幾乎在那裏,但不完全。狀態2應該從14/01/13到18/02/13。狀態8應該是25/03/13,狀態9應該運行到今天的日期 – 2013-04-25 19:56:18

0

在這一個快速更新,我想就太複雜了去,我需要答案。

這是我現在已經得到了代碼:

SELECT 
    AgreementID, 
    StatusID, 
    DateFrom, 
    CASE WHEN DateTo IS NOT NULL THEN DATEADD(S, -1, DateTo) ELSE GETDATE() END AS DateTo 
FROM 
    (
    SELECT 
     AgreementID, 
     StatusID, 
     MIN(CONVERT(datetime,StatusDate,103)) as DateFrom, 
     (SELECT TOP(1) StatusDate FROM TblStatusUpdates AS B WHERE B.StatusID > A.StatusID ORDER BY StatusID ASC, StatusDate ASC) AS DateTo 
    FROM 
     TblStatusUpdates AS A 
    GROUP BY 
     AgreementID, 
     StatusID 
    ) AS C 

這給了我下面的結果:

AgreementID StatusID DateFrom     DateTo 
109   1   2013-01-14 15:00:33.360 2013-01-14 15:01:27.393 
109   2   2013-01-14 15:01:28.393 2013-02-19 13:57:32.437 
109   8   2013-02-19 13:57:33.437 2013-03-26 15:41:49.843 
109   9   2013-03-26 15:41:50.843 2013-04-26 10:34:13.860 

謝謝大家的建議。