计算相邻行之间的时间差

Calculate time difference between adjacent rows

我有以下 table 格式

 ID   Status   Date
    16  In Review   2017-07-03 08:23:11.000
    16  Approved    2017-07-03 08:23:20.000
    16  Approved    2017-07-11 10:34:27.000

我正在尝试获取审查中和批准之间的时间差,应该是 9 秒..

这是我之前 where Gordon 为我提供答案的延续。

这是它的代码

select avg(avg_bid_diff)
from (select bid, avg(diff*1.0) as avg_bid_diff
      from (select bid, appid,
                   datediff(second, min(starttime), max(statustime)) as diff
            from t
            where appstatus in ('In Review', 'Approved')
            group by bid, appid
            having count(*) = 2
           ) ba
      group by bid
     ) b;

问题是,当它考虑最小值和最大值时,我得到第一行和第三行之间的时间差,当只有 2 个状态时,但我需要的是第一次审查和下一次审查之间的时间差批准

谁能告诉我应该如何更改查询以获得下一个批准的时差。

谢谢

这有点棘手,但目前看来效果不错。唯一的限制是对于每个唯一的(BidID,AppID)对,没有或只有一个状态为 'In Review'.

的记录

我对链式 CTE 使用了完全不同的方法:

DECLARE @table TABLE
(
    BidID int,
    AppID int,
    AppStatus nvarchar(20),
    StatusTime DATETIME2
);

INSERT INTO @table (BidID, AppID, AppStatus, StatusTime)
VALUES
(1, 1, 'In Review', '2019-01-02 12:00:00'),
(1, 1, 'Approved', '2019-01-02 13:00:00'),
(1, 1, 'Approved', '2019-01-02 13:30:00'),
(1, 2, 'In Review', '2019-01-04 13:00:00'),
(1, 2, 'Approved', '2019-01-04 15:00:00'),
(2, 2, 'Approved', '2019-01-07 14:30:00'),
(2, 2, 'In Review', '2019-01-07 15:00:00'),
(2, 2, 'Approved', '2019-01-07 16:00:00'),
(3, 1, 'In Review', '2019-01-09 13:00:00'),
(4, 1, 'Approved', '2019-01-09 13:00:00');

;WITH OrderedRecords(BidID, AppID, AppStatus, StatusTime, [Order])
AS (

    SELECT BidID
    ,AppID
    ,AppStatus
    ,StatusTime
    , [Order] = ROW_NUMBER() OVER(PARTITION BY BidID, AppID ORDER BY StatusTime)
    FROM @table
),
BidAverage(BidID, AveragePerBid)
AS (
    SELECT OR1.BidID, AVG(CAST(DATEDIFF(HOUR, OR1.StatusTime, OR2.StatusTime) AS DECIMAL)) AS AveragePerBid
    FROM OrderedRecords OR1
    INNER JOIN OrderedRecords OR2
        ON OR1.BidID = OR2.BidID AND OR1.AppID = OR2.AppID AND OR2.AppStatus = 'Approved' AND OR2.[Order] = OR1.[Order] + 1
    WHERE OR1.AppStatus = 'In Review'
    GROUP BY OR1.BidID
)
SELECT AVG(AveragePerBid) AS AveragePerTable
FROM BidAverage


AveragePerTable
---------------------------------------
1.250000

这里我试着解释一下重要的步骤:

  1. 每个 BidID、AppID、StatusTime 的记录数量 - 这只是根据状态出现的时间对记录进行编号(排序),并且每个(BidID、AppID)对重新开始编号。

    ;WITH OrderedRecords(BidID, AppID, AppStatus, StatusTime, [Order])
    AS (
    
    SELECT BidID
    ,AppID
    ,AppStatus
    ,StatusTime
    , [Order] = ROW_NUMBER() OVER(PARTITION BY BidID, AppID ORDER BY StatusTime)
    FROM @table
    )
    SELECT * FROM OrderedRecords
    
    BidID       AppID       AppStatus            StatusTime                  Order
    ----------- ----------- -------------------- --------------------------- --------------------
    1           1           In Review            2019-01-02 12:00:00.0000000 1
    1           1           Approved             2019-01-02 13:00:00.0000000 2
    1           1           Approved             2019-01-02 13:30:00.0000000 3
    1           2           In Review            2019-01-04 13:00:00.0000000 1
    1           2           Approved             2019-01-04 15:00:00.0000000 2
    2           2           Approved             2019-01-07 14:30:00.0000000 1
    2           2           In Review            2019-01-07 15:00:00.0000000 2
    2           2           Approved             2019-01-07 16:00:00.0000000 3
    3           1           In Review            2019-01-09 13:00:00.0000000 1
    4           1           Approved             2019-01-09 13:00:00.0000000 1
    
  2. 选择正确的 'In Review'、'Approved' 对记录

基本上 CTE BidAverage select 的内部 select 来自 'OrderedRecords' CTE 的所有 'InReview' 记录,并通过加入相同的 table 试图找到'Approved' 记录具有相同的 BidID、AppID 和比 'InReview' 订单高 1 的订单(这是获得相邻 'In reviw' 和 'Approved' 的技巧。INNER 连接切断 'In review' 没有 'Approved' 的记录,反之亦然。

;WITH OrderedRecords(BidID, AppID, AppStatus, StatusTime, [Order])
AS (

    SELECT BidID
    ,AppID
    ,AppStatus
    ,StatusTime
    , [Order] = ROW_NUMBER() OVER(PARTITION BY BidID, AppID ORDER BY StatusTime)
    FROM @table
)
SELECT OR1.BidID, OR1.AppID, OR1.AppStatus, OR1.StatusTime, OR1.[Order], OR2.AppStatus, OR2.StatusTime, OR2.[Order]
FROM OrderedRecords OR1
INNER JOIN OrderedRecords OR2
    ON OR1.BidID = OR2.BidID AND OR1.AppID = OR2.AppID AND OR2.AppStatus = 'Approved' AND OR2.[Order] = OR1.[Order] + 1
WHERE OR1.AppStatus = 'In Review'


BidID       AppID       AppStatus            StatusTime                  Order                AppStatus            StatusTime                  Order
----------- ----------- -------------------- --------------------------- -------------------- -------------------- --------------------------- --------------------
1           1           In Review            2019-01-02 12:00:00.0000000 1                    Approved             2019-01-02 13:00:00.0000000 2
1           2           In Review            2019-01-04 13:00:00.0000000 1                    Approved             2019-01-04 15:00:00.0000000 2
2           2           In Review            2019-01-07 15:00:00.0000000 2                    Approved             2019-01-07 16:00:00.0000000 3

当你把所有这些放在一起时(这个答案顶部的最终脚本),你就得到了你需要的。正如我上面所说,这里的限制是每个 BidID 和 AppID 只有一个 'In Review' 记录。 (但可以出现多个 'Approved' 并且 'In review' 不需要是第一个按时间)