如何计算刷卡表中的两次输入?

时间:2019-04-29 19:25:03

标签: sql sql-server-2012 ssrs-2012

如何处理刷卡表中的意外刷卡?我尝试通过将其分组来选择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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

我添加了一个小提琴来显示此功能,但我将在此处复制查询以供将来参考。

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,因为当发现重复时,您的样本返回了第二条“ Entry”记录。

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

这是最终结果。

enter image description here