0

我有一个包含状态更新的平面表。

这些更新以下列格式存储:

协议ID | 状态ID | 状态日期

源数据:

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

如您所见,Date To Value 不正确,它应该始终运行到下一个状态 ID 的前一天。

所以在这个例子中,状态 2 应该从 19/02/2013 到 18/02/13

任何建议都会很棒。谢谢你。

4

3 回答 3

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

谢谢大家的建议。

于 2013-04-26T09:39:36.780 回答
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
于 2013-04-25T16:12:43.827 回答
-1

Hopefully this is what you are looking for.

SQL FIDDLE

于 2013-04-25T18:02:15.547 回答