计算相邻行之间的时差

时间:2019-03-11 20:04:11

标签: sql sql-server sql-server-2008

我具有以下表格格式

 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

我正在尝试使In Review和Approved之间的时间差应该为9秒。

这是我先前的Question的延续,其中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;

问题是,当考虑最小和最大时,我得到了第一行和第三行之间的时间差,并且只有两个状态时,我需要的是“首次审核”与下一个“批准”之间的时间差< / p>

有人可以告诉我如何更改查询以获取下一个批准的时差。

谢谢

1 个答案:

答案 0 :(得分:1)

这有点棘手,但到目前为止看来效果不错。唯一的限制是,对于每个唯一的(BidID,AppID)对,都没有或有状态为“正在审核”的记录。

我对链式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. 选择正确的“正在审核”,“已批准”记录对

基本上,内部选择CTE BidAverage会从“ OrderedRecords” CTE中选择所有“ InReview”记录,并通过连接同一表来尝试查找具有相同BidID,AppID和Order且比“ InReview”高1的“已批准”记录'订单(这是获得相邻的“正在审核”和“已批准”的诀窍。INNER联接会切断“正在审核”的记录而没有“已批准”,反之亦然。

;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只有一个“审核中”记录。 (但是可以有多个“已批准”,而且“审核中”不必是第一个时间)