表“ audit”具有字段ID,old_status,new_status和changed_at。状态包含值打开,保留和关闭。我想确定审核保留的时间,简单计算:
SELECT Datediff(minute, (SELECT Min(changed_at)
FROM audit
WHERE id = 123
AND new_status = 'On Hold'),
(SELECT Max(changed_at)
FROM audit
WHERE id = 123
AND old_status =
'On Hold'))
但是,现在我有一个审核记录,该记录被多次保留。上面的计算确实告诉我,从第一次进入保持状态到最后一次离开保持状态之间的总时间,但是并不能反映出它实际处于保持状态的时间。
是否有一个查询可以返回该实际时间?
答案 0 :(得分:0)
在JOIN的左侧为'On Hold'且右侧为左侧之后的TOP 1记录且不为'On Hold'且具有ID
与左侧相同。
由此,您的查询只需获取左侧记录和右侧记录之间的DATEDIFF以及该DATEDIFF的总和,并按ID
分组。
答案 1 :(得分:0)
对于下面的答案,我假设一条记录的初始/默认状态为“打开”。我还假设您的SQL Server版本具有LEAD / LAG功能。
假设您有3条记录的信息。所有3条记录均以“打开”状态开头。
以下是表格形式的数据:
+----+------------+------------+------------------+
| id | old_status | new_status | changed_at |
+----+------------+------------+------------------+
| 1 | Open | On Hold | 2019-03-26 08:00 |
| 1 | On Hold | Open | 2019-03-26 09:00 |
| 1 | Open | On Hold | 2019-03-26 10:00 |
| 1 | On Hold | Closed | 2019-03-26 11:00 |
| 2 | Open | On Hold | 2019-03-26 08:00 |
| 2 | On Hold | Closed | 2019-03-26 09:00 |
| 3 | Open | On Hold | 2019-03-26 08:00 |
+----+------------+------------+------------------+
根据数据以及我对您的问题的了解,您希望保留记录的总时间。因此,对于上面的3条记录:
要开始解决该问题,您可以首先使用WINDOW函数查看相关结果。我最终使用了LAG
。
首先,您可以使用LAG
找出(记录中)最后一次更改发生的位置:
SELECT
[id],
old_status,
new_status,
changed_at,
prev_changed = LAG(changed_at) OVER
(
PARTITION BY [id]
ORDER BY [id], changed_at
)
FROM audit_records
这将为您提供以下结果:
+----+------------+------------+------------------+------------------+
| id | old_status | new_status | changed_at | prev_changed |
+----+------------+------------+------------------+------------------+
| 1 | Open | On Hold | 2019-03-26 08:00 | NULL |
| 1 | On Hold | Open | 2019-03-26 09:00 | 2019-03-26 08:00 |
| 1 | Open | On Hold | 2019-03-26 10:00 | 2019-03-26 09:00 |
| 1 | On Hold | Closed | 2019-03-26 11:00 | 2019-03-26 10:00 |
| 2 | Open | On Hold | 2019-03-26 08:00 | NULL |
| 2 | On Hold | Closed | 2019-03-26 09:00 | 2019-03-26 08:00 |
| 3 | Open | On Hold | 2019-03-26 08:00 | NULL |
+----+------------+------------+------------------+------------------+
请注意记录值为NULL:这些是之前没有更改的记录。因此,对于记录1,从打开到保留的更改为空,因为这是第一个更改。
现在您可以将其包装在CTE中并计算分钟数:
WITH
audit_records_lead_lag([id], old_status, new_status, changed_at, prev_changed) AS
(
SELECT
[id],
old_status,
new_status,
changed_at,
prev_changed = LAG(changed_at) OVER
(
PARTITION BY [id]
ORDER BY [id], changed_at
)
FROM audit_records
)
SELECT
[id],
minutes_in_hold = SUM(DATEDIFF(MINUTE, prev_changed, changed_at))
FROM audit_records_lead_lag
WHERE
old_status = 'On Hold'
AND prev_changed IS NOT NULL
GROUP BY [id]
为您提供以下结果:
+----+-----------------+
| id | minutes_in_hold |
+----+-----------------+
| 1 | 120 |
| 2 | 60 |
+----+-----------------+