如何计算刷卡 table 中的重复条目?

How to account for double entries in a card swipe table?

如何计算刷卡中的意外刷卡 table?我尝试通过在输入时将它们分组来选择 max(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

您可以使用 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

然后您可以使用此结果进行任何需要的处理。一个例子是将上面的内容放在一个常见的 table 表达式中并使用另一个查询。请注意,您必须添加 "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 = ''

我添加了一个 fiddle 来展示这个工作,但我会在此处复制查询以供将来参考。

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

下面非常接近 fiddle 版本,只是使用临时 table 而不是永久 table.

另外,我编辑了示例数据,因为最后两条记录的名称之间有额外的空格。我认为这是错误的。

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 Name 以避免排除行 TimeATT 连续两行的列相同,但针对不同的人。

我使用 LEAD 而不是 LAG,因为您的样本在发现重复项时返回了第二条 "Entry" 记录。

这可以用 CTE 写得更优雅,但这确实有效。

这是最终结果..