Как учесть двойные записи в карточной таблице? - PullRequest
0 голосов
/ 29 апреля 2019

Как я могу учесть случайные пролистывания в таблице карточек? Я попытался выбрать максимум (time_cst), сгруппировав их при входе. Это не решило проблему. http://www.sqlfiddle.com/#!18/06cc8/2

EmpID   Enter/Exit  Time 
 2999   Entry   06:00AM 
 2999   Entry   06:01AM 
 2999   Exit    12:00PM
 2999   Entry   01:00PM 
 2999   Exit    03:00PM 
 2999   Entry   04:00PM
 2999   Exit    06:00PM

Вот как я хочу, чтобы это появилось. http://www.sqlfiddle.com/#!18/5cfbb/2

EmpID   EntryTime  ExitTime
 2999   06:01AM    12:00PM
 2999   01:00PM    03:00PM
 2999   04:00PM    06:00PM

Ответы [ 2 ]

1 голос
/ 30 апреля 2019

Я добавил скрипку, чтобы показать эту работу, но я скопирую запрос здесь для дальнейшего использования.

http://www.sqlfiddle.com/#!18/87593fe/12/0

Ниже очень близко к версии скрипта, простоиспользуя временную таблицу вместо постоянной.

Кроме того, я отредактировал пример данных, так как между именами в последних двух записях были лишние пробелы.Я предполагаю, что это было ошибкой.

DROP TABLE IF EXISTS #Table1
CREATE TABLE #Table1
    ([Name] varchar(9), [TimeATT] int, [DateTime] varchar(19))
;

INSERT INTO #Table1
    ([Name], [TimeATT], [DateTime])
VALUES
    ('jane doe', 1, '2019-04-23T08:00:00'),
    ('jane doe', 1, '2019-04-23T08:01:01'),
    ('jane doe', 2, '2019-04-23T12:00:00'),
    ('jane doe', 1, '2019-04-23T12:05:00'),

    ('john doe', 1, '2019-04-23T08:00:00'),
    ('john doe', 2, '2019-04-23T09:00:01'),
    ('john doe', 1, '2019-04-23T09:05:00'),
    ('john doe', 2, '2019-04-23T12:00:00')

SELECT [Name],[EntryTime], [ExitTime]
 FROM ( -- sub query to get matching exit time for each entry if it exists
        SELECT 
         [Name],
         [DateTime] as EntryTime,
         LEAD([DateTime], 1, NULL) OVER(PARTITION BY [Name] ORDER BY [DateTime]) AS ExitTime
         ,TimeATT, [DateTime]
        FROM ( -- subquery to exclude duplicate records
                SELECT * FROM ( -- subquery to identify records to ignore
                              SELECT 
                                  [Name], [TimeATT], [DateTime],
                                  CASE LEAD(TimeATT, 1, 0) OVER(PARTITION BY [Name] ORDER BY [DateTime]) 
                                    WHEN TimeATT THEN 1
                                    ELSE 0
                                  END AS Exclude
                              FROM #Table1) a
                              WHERE Exclude = 0
              ) t
        ) z
  WHERE [TimeATT] = 1 -- filter so left column is always entry time.
  ORDER BY [Name], [DateTime]

Примечание Для функции LEAD необходимо partitioned by Имя, чтобы избежать исключения строк, в которых столбец TimeATT совпадает в двух последовательных строках, нодля разных людей.

Я использовал LEAD вместо LAG, так как ваш образец возвратил 2-ую запись "Entry", когда были найдены дубликаты.

Это может быть написано более элегантно с CTE, но это работает.

Вот окончательный результат ..

enter image description here

1 голос
/ 29 апреля 2019

Вы можете использовать функцию LAG, чтобы просмотреть предыдущую строку и посмотреть, является ли значение TimeATT одинаковым (упорядочение по имени, а затем по времени).

Это требует, чтобы никогда не было возможности перекрывающихся транзакций.,Также обратите внимание, что порядок в функции LAG и в вашем запросе должны быть одинаковыми в этом случае.

  select [Name], [TimeATT], [DateTime],
  case when LAG(TimeATT)OVER(order by [Name],[DateTime]) = TimeATT then 'Dup'
  else ''
  end as Dup
  from Table1
  order by [Name],[DateTime]

http://www.sqlfiddle.com/#!18/06cc8/14/0

Затем можно использовать результаты этого, чтобы сделатькакая бы обработка не требовалась.Одним из примеров было бы поместить вышеупомянутое в общее табличное выражение и использовать другой запрос.Обратите внимание, что вы должны добавить «TOP XXX», чтобы получить заказ для работы в CTE, поэтому мы должны принудительно установить его, поскольку он необходим для данных.

  WITH DupsMarked as (
  select top 100 PERCENT [Name], [TimeATT], [DateTime],
  case when LAG(TimeATT)OVER(order by [Name],[DateTime]) = TimeATT then 'Dup'
  else ''
  end as Dup
  from Table1
  order by [Name],[DateTime]
  )
  SELECT * FROM DupsMarked where Dup = ''
...