sql-server-2019 - 实时监控
问题描述
我试图确定员工何时在多个主要位置同时显示 in(1) 的打卡状态。如果他们在同一个主要位置的多个子位置被打孔,那很好,因为这将是工作的正常部分。但是,应该不可能在多个主要位置打卡,这些都需要进行审查。下面我已经包含了表格的布局以及信息以及一组样本数据。在这个样本集中,我们正在研究我们可以预期的三种类型的场景。绿色部分显示同一主要位置的输入 (1) 和输出 (2),当天没有其他主要位置,甚至没有子位置。蓝色部分显示重叠的打孔,但它们位于相同的主要位置,只是不同的子位置,这也很好。然而,橙色部分是我们想要找到的。本节显示不同主要位置的重叠打孔。我希望从输出中看到两条记录,它们显示了不同位置的 ins 信息。所以在这种情况下,只需输出前两条橙色线。我希望能够尽可能近乎实时地识别这一点,并将输出发送到电子邮件发行版以供审查。由于时间范围可能变化很大,因此仅监视最后一两个小时并不总是有足够的数据,如本例所示。我正在考虑检查当前存在于进出之间的最长时间范围,然后将其加倍并将其用于监控时间范围,但我不确定这是否是正确的方法。本节显示不同主要位置的重叠打孔。我希望从输出中看到两条记录,它们显示了不同位置的 ins 信息。所以在这种情况下,只需输出前两条橙色线。我希望能够尽可能近乎实时地识别这一点,并将输出发送到电子邮件发行版以供审查。由于时间范围可能变化很大,因此仅监视最后一两个小时并不总是有足够的数据,如本例所示。我正在考虑检查当前存在于进出之间的最长时间范围,然后将其加倍并将其用于监控时间范围,但我不确定这是否是正确的方法。本节显示不同主要位置的重叠打孔。我希望从输出中看到两条记录,它们显示了不同位置的 ins 信息。所以在这种情况下,只需输出前两条橙色线。我希望能够尽可能近乎实时地识别这一点,并将输出发送到电子邮件发行版以供审查。由于时间范围可能变化很大,因此仅监视最后一两个小时并不总是有足够的数据,如本例所示。我正在考虑检查当前存在于进出之间的最长时间范围,然后将其加倍并将其用于监控时间范围,但我不确定这是否是正确的方法。我希望从输出中看到两条记录,它们显示了不同位置的 ins 信息。所以在这种情况下,只需输出前两条橙色线。我希望能够尽可能近乎实时地识别这一点,并将输出发送到电子邮件发行版以供审查。由于时间范围可能变化很大,因此仅监视最后一两个小时并不总是有足够的数据,如本例所示。我正在考虑检查当前存在于进出之间的最长时间范围,然后将其加倍并将其用于监控时间范围,但我不确定这是否是正确的方法。我希望从输出中看到两条记录,它们显示了不同位置的 ins 信息。所以在这种情况下,只需输出前两条橙色线。我希望能够尽可能近乎实时地识别这一点,并将输出发送到电子邮件发行版以供审查。由于时间范围可能变化很大,因此仅监视最后一两个小时并不总是有足够的数据,如本例所示。我正在考虑检查当前存在于进出之间的最长时间范围,然后将其加倍并将其用于监控时间范围,但我不确定这是否是正确的方法。我希望能够尽可能近乎实时地识别这一点,并将输出发送到电子邮件发行版以供审查。由于时间范围可能变化很大,因此仅监视最后一两个小时并不总是有足够的数据,如本例所示。我正在考虑检查当前存在于进出之间的最长时间范围,然后将其加倍并将其用于监控时间范围,但我不确定这是否是正确的方法。我希望能够尽可能近乎实时地识别这一点,并将输出发送到电子邮件发行版以供审查。由于时间范围可能变化很大,因此仅监视最后一两个小时并不总是有足够的数据,如本例所示。我正在考虑检查当前存在于进出之间的最长时间范围,然后将其加倍并将其用于监控时间范围,但我不确定这是否是正确的方法。
我已经考虑过将数据输入到表/视图中,该表/视图仅保留活动的出拳,并且当有人出拳时,它只会删除输入。然后为同一个 EmpID 有多个记录时设置某种标志不同的主要位置发送通知。我只是不知道该怎么做。任何关于如何做到这一点或我可以研究可能有帮助的事情的想法将不胜感激。此数据存储在 SQL 2019 服务器中。它是我们的报告服务器,正在使用复制从生产服务器提供数据。我们可以添加任何可能有用的列/索引或其他对象。
Create Table TimeSheet(
EmpID int not null
,PrimaryLocation int not null
,SubLocation int not null
,PunchStatus smallint not null ----(1 in, 2 out)
,PunchTime DateTime not null
)
编辑:
现在发布我自己的问题的答案还为时过早,但我认为我得到了可以工作的代码。我什至添加了一些额外的场景来测试,它适用于这些场景。我仍然需要在实际数据库上对其进行测试,该数据库每天将有数百万条记录,但以下是我使用的。它可能会大大改进,如果您对此有任何想法,请告诉我。
If OBJECT_ID('tempdb.dbo.#TimeSheet') IS NOT NULL DROP TABLE #TimeSheet
If OBJECT_ID('tempdb.dbo.#Test') IS NOT NULL DROP TABLE #Test
If OBJECT_ID('tempdb.dbo.#Window') IS NOT NULL DROP TABLE #Window
If OBJECT_ID('tempdb.dbo.#WindowPrep') IS NOT NULL DROP TABLE #WindowPrep
Create Table #TimeSheet(
EmpID int not null
,PrimaryLocation int not null
,SubLocation int not null
,PunchStatus smallint not null ----(1 in, 2 out)
,PunchTime DateTime not null
)
Insert Into #TimeSheet
Values (1,5,2,1,'5/2/21 12:56 PM')
,(1,5,2,2,'5/2/21 3:00 PM')
,(1,4,2,1,'5/2/21 3:56 PM')
,(1,4,2,2,'5/2/21 5:00 PM')
,(1,4,2,1,'5/5/21 8:24 PM')
,(1,4,1,1,'5/5/21 9:24 PM')
,(1,4,1,2,'5/5/21 10:24 PM')
,(1,4,2,2,'5/5/21 11:24 PM')
,(1,2,8,1,'5/20/21 8:44 AM')
,(1,2,7,1,'5/20/21 9:44 AM')
,(1,2,7,2,'5/20/21 3:44 PM')
,(1,3,2,1,'5/20/21 5:52 PM')
,(1,3,2,2,'5/20/21 6:30 PM')
,(1,2,8,2,'5/20/21 6:00 PM')
;With cte_In
as
(
select
EmpID
,PrimaryLocation
,SubLocation
,PunchStatus as PunchIn
,PunchTime as InTime
From #TimeSheet as T
Where T.PunchStatus = 1
)
,cte_Out
as
(
select
EmpID
,PrimaryLocation
,SubLocation
,PunchStatus as PunchOut
,PunchTime as OutTime
From #TimeSheet as T
Where T.PunchStatus = 2
)
Select
ROW_NUMBER() Over(Order by I.InTime) as NewRecordNum
,I.EmpID
,I.PrimaryLocation
,I.SubLocation
,I.PunchIn
,I.InTime
,Max(O.OutTime) as OutTime
Into #Test
From cte_In as I
Left Join cte_Out as O
on I.EmpID = O.EmpID
and I.PrimaryLocation = O.PrimaryLocation
and I.SubLocation = O.SubLocation
and I.InTime < O.OutTime
Group by
I.EmpID
,I.PrimaryLocation
,I.SubLocation
,I.PunchIn
,I.InTime
Select
T.*
,Max(OutTime) Over (Partition by Cast(Intime as date) Order by NewRecordNum) as PriorOutPrep
,Lag(T.PrimaryLocation,1) Over (Partition by Cast(Intime as date) Order by NewRecordNum) as PriorPrim
Into #WindowPrep
From #Test as T
Select *,Lag(PriorOutPrep,1) Over(Partition by Cast(InTime as Date) Order by NewRecordNum) as PriorOut
Into #window
From #WindowPrep
;With cte_Final
as
(
Select
W.EmpID
,W.NewRecordNum
,W.PriorOut
From #Window as W
Where W.PrimaryLocation <> W.PriorPrim
and W.InTime < W.PriorOut
)
Select
W.EmpID
,W.PrimaryLocation
,W.SubLocation
,W.InTime
,W.OutTime
From #window as W
Join cte_Final as F
on W.EmpID = F.EmpID
and (
W.NewRecordNum = F.NewRecordNum
or
W.OutTime = F.PriorOut
)
解决方案
推荐阅读
- palantir-foundry - 是否可以将代码工作簿恢复到以前的版本?
- c++ - Boost 日志在 W10 上工作但不在 ubuntu 中 - 分段错误
- dc.js - 计算不包括重复的记录
- rancher - 如何在 Rancher Web UI 中使用自定义 SSL 证书?
- python - 将几个 .c cython 模块构建到一个 .exe 中
- php - 这个 API 存储库是有效的还是应该拆分为服务?
- excel - Excel 结构化参考 - 使用 @ 或 #This Row 检索当前行不起作用
- user-interface - 你怎么称呼像这样的 UI 元素的甜甜圈形仪表?
- vue.js - vueJS 3.x:在 HTML 表单提交后从页面导航
- typescript - `(function(): Something{})` 语法的目的是什么?