根据另一列的每个实例的最大日期使用DATEDIFF

时间:2019-02-07 20:59:50

标签: sql sql-server

我有一个状态表,其中包含orderNO,Insert_Date和状态。我的目标是确定状态更改之间的时间间隔。问题是,如果输入订单的任何人多次单击状态更改按钮,我将获得每个状态的多个实例。我在下面拉了一个特定orderNO的示例:

+------------+---------+--------------------------+
|  orderNO   | status  |       insert_date        |
+------------+---------+--------------------------+
| OBJV107522 | ENTERED | 2/4/2019 11:44:45.800 AM |
| OBJV107522 | ENTERED | 2/4/2019 11:45:14.410 AM |
| OBJV107522 | ENTERED | 2/4/2019 11:45:14.597 AM |
| OBJV107522 | ENTERED | 2/4/2019 11:45:14.833 AM |
| OBJV107522 | OPEN    | 2/4/2019 12:27:15.710 PM |
| OBJV107522 | ENTERED | 2/4/2019 12:36:39.327 PM |
| OBJV107522 | ENTERED | 2/4/2019 12:36:39.920 PM |
| OBJV107522 | OPEN    | 2/4/2019 2:34:58.957 PM  |
| OBJV107522 | ENTERED | 2/4/2019 2:35:07.817 PM  |
| OBJV107522 | OPEN    | 2/4/2019 3:50:04.393 PM  |
+------------+---------+--------------------------+

理想情况下,我希望看到状态更改之间经过的分钟数。输出将需要像这样。

  • 第一行应该是状态更改之前所有“输入”的最大实例数减去状态更改之前所有“打开”的最大实例数。
  • 下一行应该是第一个“ OPEN”实例的最大值(在状态更改回“ ENTERED”之前,减去第二个“ ENTERED”的最大值)。

    +------------+------------+-----------------+ | orderNO | New_status | minutes_elapsed | +------------+------------+-----------------+ | OBJV107522 | OPEN | 42 | 4th row - 5th row of the original data | OBJV107522 | ENTERED | 9 | 5th row-7th row of the original data | OBJV107522 | OPEN | 118 | | OBJV107522 | ENTERED | 0 | | OBJV107522 | OPEN | 75 | +------------+------------+-----------------+

我无法独自尝试。我开始说服自己这是不可能的。请让我知道任何建议。

2 个答案:

答案 0 :(得分:2)

也许这样的事情可以利用窗口功能。

WITH CTE AS(
    SELECT *, 
        LAG( status) OVER( PARTITION BY orderNO ORDER BY insert_date) AS Previous_Status, 
        LAG( insert_date) OVER( PARTITION BY orderNO ORDER BY insert_date) AS Previous_Date
    FROM OrderStatus
)
SELECT orderNO,
    status,
    DATEDIFF(mi, Previous_Date, insert_date) AS minutes_elapsed,
    ROUND(DATEDIFF(ss, Previous_Date, insert_date)/60., 0) AS minutes_elapsed2 /*This actually matches your expected results*/
FROM CTE
WHERE status <> Previous_Status;

答案 1 :(得分:0)

DECLARE @t TABLE (orderNO VARCHAR(20),status  VARCHAR(20), insert_date DATETIME)

INSERT INTO @t VALUES
(' OBJV107522 ',' ENTERED ',' 2/4/2019 11:44:45.800 AM '),
(' OBJV107522 ',' ENTERED ',' 2/4/2019 11:45:14.410 AM '),
(' OBJV107522 ',' ENTERED ',' 2/4/2019 11:45:14.597 AM '),
(' OBJV107522 ',' ENTERED ',' 2/4/2019 11:45:14.833 AM '),
(' OBJV107522 ',' OPEN    ',' 2/4/2019 12:27:15.710 PM '),
(' OBJV107522 ',' ENTERED ',' 2/4/2019 12:36:39.327 PM '),
(' OBJV107522 ',' ENTERED ',' 2/4/2019 12:36:39.920 PM '),
(' OBJV107522 ',' OPEN    ',' 2/4/2019 2:34:58.957 PM  '),
(' OBJV107522 ',' ENTERED ',' 2/4/2019 2:35:07.817 PM  '),
(' OBJV107522 ',' OPEN    ',' 2/4/2019 3:50:04.393 PM  ');

SELECT t2.orderNO, t2.status, t2.insert_date
    , minutes_elapsed  = MAX(DATEDIFF(SECOND, t.insert_date, t2.insert_date)/60)
FROM @t as t
CROSS APPLY (
    SELECT insert_date = MIN(t1.insert_date) 
    FROM @t as t1
    WHERE t1.status != t.status 
        and t1.insert_date > t.insert_date
) as tm
INNER JOIN @t as t2 ON t2.insert_date = tm.insert_date 
GROUP BY t2.orderNO, t2.status, t2.insert_date
ORDER BY t2.insert_date