В ответе ниже я предполагаю, что исходное / заданное по умолчанию состояние записи - «Открыть».Я также предполагаю, что ваша версия SQL Server имеет функции LEAD / LAG.
Допустим, у вас есть информация о 3 записях.Все 3 записи начинаются со статуса «Открыто».
- Для Записи 1 состояние менялось 4 раза:
- В 8:00 оно было изменено с Открыто на Удержание..
- В 9:00 оно было изменено с «Удержание» на «Открытие». * 10:00
- С 10:00 оно было снова переведено на «Удержание».: 00.
- Для записи 2 статус был изменен дважды:
- В 8:00 он был изменен с «Открыто» на «Удержание».
- В 9:00 оно было изменено на Закрыто.
- Запись 3 имеет только одно изменение:
- В 8:00 оно было изменено с Открытого на Удержание(имеется в виду, что текущий статус находится на удержании).
Вот данные в табличной форме:
+----+------------+------------+------------------+
| 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 вышеуказанных записей:
- Запись 1 была приостановлена в общей сложности 2 часа / 120 минут: 1 час с 8 до 9, затем еще один час с 10 до 11.
- Запись 2 была приостановлена всего на 1 час: с 8 до 9.
- Для записи 3 неясно, каковы ваши ожидаемые результаты: будут ли результаты с 8:00 (когда они были помещены наудерживать) до текущей даты / времени?Или вы хотите исключить это из своих результатов?
Чтобы начать атаку на проблему, сначала вы можете использовать функции 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 |
+----+-----------------+