SQL Sum Datediff有条件地使用不同的行

时间:2016-07-13 03:07:24

标签: sql sql-server-2008 datediff row-number

我不是一名DBA,我知道自己陷入困境就是在这里忍受我。我试图从一组数据中找到日期差异,但只根据状态变化计算记录之间的条件差异。我所遇到的问题不是根据我需要的规则计算天数。

使用SQL 2008 R2,遵循以下规则:

  • 记录oldValue到newValue的位置(对'任何'为NULL)将始终= MIN;
  • 仅当oldValue不等于Close或Deferred时才添加日期计数;
  • 请勿在之前已知的newValue等于当前记录oldValue且等于Closed或Deferred
  • 的更改之间添加日计数

使用:

declare @t table
(
    tranID int,
    orderNum varchar(20),
    oldValue varchar(2000),
    newValue varchar(2000),
tranTime datetime
)

insert into @t values(140,3, NULL, 'Closed', '2013-01-05 12:00:00.000')
insert into @t values(160,4, NULL, 'Defered', '2013-01-07 18:00:00.000')
insert into @t values(101,5, NULL, 'New', '2013-01-01 10:01:00.000')
insert into @t values(111,5, 'New', 'Closed', '2013-01-02 10:00:00.000')
insert into @t values(102,6, NULL, 'New', '2013-01-01 10:02:00.000')
insert into @t values(112,6, 'Open', 'Deferred', '2013-01-02 10:10:00.000')
insert into @t values(132,6, 'Deferred', 'Closed', '2013-01-04 11:00:00.000')
insert into @t values(103,7, NULL, 'New', '2013-01-01 10:03:00.000')
insert into @t values(123,7, 'Ready', 'Closed', '2013-01-03 11:30:00.000')
insert into @t values(133,7, 'Closed', 'Open', '2013-01-04 11:11:00.000')
insert into @t values(143,7, 'Passed', 'Closed', '2013-01-05 12:15:00.000')
insert into @t values(104,8, NULL, 'New', '2013-01-01 10:04:00.000')
insert into @t values(114,8, 'Open', 'Closed', '2013-01-02 10:20:00.000')
insert into @t values(134,8, 'Closed', 'Open', '2013-01-04 11:22:00.000')
insert into @t values(144,8, 'Failed', 'Deferred', '2013-01-05 12:30:00.000')
insert into @t values(154,8, 'Deferred', 'Closed', '2013-01-06 17:00:00.000')

我希望看到类似的输出:

orderNum | resolveDays
----------------------
    3    |      0
    4    |      0
    5    |      1
    6    |      1
    7    |      3
    8    |      2

我们有一组订单,其交易根据更改的日期增加ID。已排序的tranID将依次对日期进行排序。要查看我们需要通过orderNum然后tranID订购的规则轻松分组的数据,您可以看到orderNum与发生顺序的匹配更改很好地排列。 我有一个查询,它将为我提供最小和最大日期的日期差异,但这不符合规则,我没有添加天,而订单被关闭或延期。

Select orderNum
      ,MIN(tranTime)as Opened
      ,MAX(tranTime) as LastClose
      ,DATEDIFF(DAY,MIN(tranTime),MAX(tranTime)) as resolveDays
      ,Count(tranTime) as QtyChanged
from @t 
group by orderNum
order by orderNum

我试图用一个案例开关来总结orderNum但是无法正确显示计数导致我尝试使用RANK或ROW_NUMBER在orderNum上对前一个记录进行自联接并检查案例oldValue和newValue的条件,但我错过了连接件的东西。我一直在关注岛屿和间隙解决方案,但我无法连接这些点以获得我预期的结果。我还能在这里尝试什么?

1 个答案:

答案 0 :(得分:0)

尝试以下查询

DECLARE @t TABLE
(
    tranID INT,
    orderNum VARCHAR(20),
    oldValue VARCHAR(2000),
    newValue VARCHAR(2000),
    tranTime DATETIME
)

INSERT INTO @t VALUES(140,3, NULL, 'Closed', '2013-01-05 12:00:00.000')
INSERT INTO @t VALUES(160,4, NULL, 'Defered', '2013-01-07 18:00:00.000')
INSERT INTO @t VALUES(101,5, NULL, 'New', '2013-01-01 10:01:00.000')
INSERT INTO @t VALUES(111,5, 'New', 'Closed', '2013-01-02 10:00:00.000')
INSERT INTO @t VALUES(102,6, NULL, 'New', '2013-01-01 10:02:00.000')
INSERT INTO @t VALUES(112,6, 'Open', 'Deferred', '2013-01-02 10:10:00.000')
INSERT INTO @t VALUES(132,6, 'Deferred', 'Closed', '2013-01-04 11:00:00.000')
INSERT INTO @t VALUES(103,7, NULL, 'New', '2013-01-01 10:03:00.000')
INSERT INTO @t VALUES(123,7, 'Ready', 'Closed', '2013-01-03 11:30:00.000')
INSERT INTO @t VALUES(133,7, 'Closed', 'Open', '2013-01-04 11:11:00.000')
INSERT INTO @t VALUES(143,7, 'Passed', 'Closed', '2013-01-05 12:15:00.000')
INSERT INTO @t VALUES(104,8, NULL, 'New', '2013-01-01 10:04:00.000')
INSERT INTO @t VALUES(114,8, 'Open', 'Closed', '2013-01-02 10:20:00.000')
INSERT INTO @t VALUES(134,8, 'Closed', 'Open', '2013-01-04 11:22:00.000')
INSERT INTO @t VALUES(144,8, 'Failed', 'Deferred', '2013-01-05 12:30:00.000')
INSERT INTO @t VALUES(154,8, 'Deferred', 'Closed', '2013-01-06 17:00:00.000')
------
DECLARE @TmpTable TABLE 
(
    Id INT,
    tranID INT,
    orderNum VARCHAR(20),
    oldValue VARCHAR(2000),
    newValue VARCHAR(2000),
    tranTime DATETIME
)
------
INSERT INTO @TmpTable
SELECT
    ROW_NUMBER() OVER(PARTITION BY orderNum ORDER BY tranID) Id,
    tranID,
    orderNum,
    oldValue,
    newValue,
    tranTime
FROM
    @t    
------
SELECT 
    CurrentRow.orderNum,
    SUM(
        CASE
            WHEN CurrentRow.newValue = NextRow.oldValue AND 
                 NextRow.oldValue IN ('Closed', 'Deferred') THEN 0
            ELSE ISNULL(DATEDIFF(DAY, CurrentRow.tranTime, NextRow.tranTime), 0) END
        )  AS resolveDays
FROM
    @TmpTable CurrentRow LEFT JOIN 
    @TmpTable NextRow ON CurrentRow.orderNum = NextRow.orderNum AND
                         CurrentRow.Id = (NextRow.Id - 1)
GROUP BY CurrentRow.orderNum

输出:

orderNum             resolveDays
-------------------- -----------
3                    0
4                    0
5                    1
6                    1
7                    3
8                    2