Выберите самое последнее и самое раннее время в пределах временной группы и сводную инструкцию - PullRequest
0 голосов
/ 31 декабря 2018

У меня есть данные, содержащие имя пользователя, время и статус (IN или OUT).Я хочу показать данные о посещаемости, которые содержат имя и время заезда / выезда.Я ожидаю, что человек будет проверять и выходить не чаще, чем два раза в день.Данные выглядят так:

Commercial Photography

Как видите, моя проблема в том, что один человек может иметь несколько записей данных в разные секунды для одного и того же входапопытка.Это связано с тем, что я получаю данные со сканера отпечатков пальцев, а аппарат в некоторых случаях делает несколько записей, иногда всего за 5-10 секунд.Я хочу выбрать данные так:

Commercial Photography

Как определить правильное время для попытки входа в систему, а затем выбрать данные с помощьюстержень?

1 Ответ

0 голосов
/ 31 декабря 2018

Во-первых, вам нужно нормализовать ваши данные, удалив дублирующиеся записи.В вашей ситуации это сложная задача, поскольку дублированные данные нелегко идентифицировать как дубликаты.Вы можете сделать некоторые предположения, хотя.Ниже я предполагаю, что никто не будет делать несколько попыток входа в систему в двухминутном окне.Вы можете сделать это сначала с помощью 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

...