Во-первых, вам нужно нормализовать ваши данные, удалив дублирующиеся записи.В вашей ситуации это сложная задача, поскольку дублированные данные нелегко идентифицировать как дубликаты.Вы можете сделать некоторые предположения, хотя.Ниже я предполагаю, что никто не будет делать несколько попыток входа в систему в двухминутном окне.Вы можете сделать это сначала с помощью Common Table Expression (CTE, используя предложение WITH
).
В CTE вы можете использовать функцию LAG
.По сути, этот код говорит: «Для каждого раздела пользователя и типа записи, если предыдущее значение было в течение 2 минут после этого значения, затем введите число, в противном случае - ноль».Я выбрал ноль в качестве флага, который будет сохранять значение, потому что LAG
первой записи будет нулевым.Итак, ваш CTE просто вернет таблицу событий входа (ID), которые были отдельными попытками.
Теперь вы готовите другой CTE, из которого PIVOT
будет извлекать, который имеет все из вашей таблицы, но только дляидентификаторы записей, о которых вы заботилисьPIVOT
будет просматривать минимальное / максимальное значения времени ввода / вывода.
WITH UNIQUE_LOGINS AS (
SELECT ID FROM LOGIN_TABLE
WHERE CASE WHEN LAG(TIME, 1, 0) OVER (PARTITION BY USERNAME, STATUS ORDER BY TIME)
+ (2/60/24) < TIME THEN NULL ELSE 1 END IS NULL ), -- Times within 2 minutes
TEMP_FOR_PIVOT AS (
SELECT USERNAME, TIME, STATUS FROM LOGIN_TABLE WHERE ID IN (SELECT ID FROM UNIQUE_LOGINS)
)
SELECT * FROM TEMP_FOR_PIVOT
PIVOT (
MIN(TIME), MAX(TIME) FOR STATUS IN ('IN', 'OUT')
)
Оттуда, если вам нужно переставить или переименовать столбцы, вы можете просто поставить последний SELECT
в еще один CTE, а затем выберите из него свои значения.Еще немного о PIVOT
здесь: Поворот / сводная таблица с агрегацией в Oracle