我是 sql 的新手,我被安排了一个创建查询的任务,该查询将为我提供每个用户的第一个和最后一个入口以及他们在办公室的时间。 到目前为止,我得到了以下内容
SELECT
CONVERT(VARCHAR(10),evts.Eventtime,101) as Date,
CONVERT(VARCHAR(10),evts.Eventtime,108) as Time,
un.UserName AS [User],
case
when p.Name = 'ACU:4321104 - 5th floor (In)' then '5th entrance'
when p.name = 'ACU:4321176 - 4th floor (In)' then '4th entrance'
when p.name = 'ACU:4321176 - 4th floor (Out)' then '4th exit'
when p.name = 'ACU:4321104 - 5th floor (Out)' then '5th exit'
when p.name = 'ACU:4321158 - 3rd Floor (In)' then '3rd entrance'
when p.name = 'ACU:4321158 - 3rd Floor (Out)' then '3rd exit'
end as [where]
FROM
Net2Events.dbo.Events AS evts LEFT OUTER JOIN
dbo.vw_UserNamesFS AS un ON evts.UserID = un.UserID LEFT OUTER JOIN
Net2Events.dbo.[Event subtype description] AS esd ON evts.EventSubType = esd.EventSubType LEFT OUTER JOIN
Net2Events.dbo.[Event description] AS ed ON evts.EventType = ed.EventType LEFT OUTER JOIN
dbo.Peripherals AS p ON evts.Address = p.Address AND evts.SubAddr = p.SubAddr
WHERE evts.EventTime >= dateadd(day,datediff(day,1,GETDATE()),0)
AND evts.EventTime < dateadd(day,datediff(day,0,GETDATE()),0)
它允许访问每个入口和导出。任何帮助将不胜感激。
谢谢
最佳答案
您几乎肯定需要调整您的 where
子句,如果这不是一次性报告,但对于所有 EventTime
在这两个日期之间,此查询将为您提供第一个和最后一个 EventTime
每个用户和他们之间的时间(以分钟为单位)。
如果您需要按特定的花语进一步分割,您可以添加 where
字段返回(虽然我不建议使用该名称,因为它是一个 SQL 关键字)到 select
和 group by
:
SELECT un.UserName AS [User]
,MIN(evts.Eventtime) as FirstEvent
,MAX(evts.Eventtime) as LastEvent
,DATEDIFF(minute,MIN(evts.Eventtime),MAX(evts.Eventtime)) as TimeDifference
FROM Net2Events.dbo.Events AS evts
LEFT OUTER JOIN dbo.vw_UserNamesFS AS un
ON evts.UserID = un.UserID
LEFT OUTER JOIN Net2Events.dbo.[Event subtype description] AS esd
ON evts.EventSubType = esd.EventSubType
LEFT OUTER JOIN Net2Events.dbo.[Event description] AS ed
ON evts.EventType = ed.EventType
LEFT OUTER JOIN dbo.Peripherals AS p
ON evts.Address = p.Address
AND evts.SubAddr = p.SubAddr
WHERE evts.EventTime >= dateadd(day,datediff(day,1,GETDATE()),0)
AND evts.EventTime < dateadd(day,datediff(day,0,GETDATE()),0)
GROUP BY un.UserName
不过,我认为您需要做的不仅仅是第一个和最后一个事件,因为我认为世界上没有 100% 正确数据的生产数据库。这意味着您需要找到最早的 In
事件及最新Out
事件,然后检查这些是否有意义。
您可以从聚合中“排除”某些行,例如 min
和 max
用一个 case 语句替换一个超出正常范围的不可能的值,如果以后需要,你可以处理:
min(case when <criteria to include> then EventTime else '29990101' end)
编辑以响应评论添加
要将您的时差格式化为各种日期元素,您需要从最大的日期部分开始 - 即:天?小时? - 然后从那里开始工作。从计算您有多少天开始,对于以分钟为单位的值,这意味着将整数除以 60 得到完整的小时数,然后除以 24 得到完整的天数:
@difference / 60 / 24
然后我们需要完整小时数减去全天占用的所有小时数。为此,我们可以使用 modulo
进行上述计算。而不是 division
找到不构成一整天的剩余时间:
@difference / 60 % 24
然后要找到剩余的分钟数,我们只需要找到除以 60 的余数:
@difference % 60
做一些cast/convert
获得正确的格式,您将在天、小时和分钟方面有所不同:
declare @start datetime = getdate() - 400.255;
declare @end datetime = getdate();
declare @difference int = datediff(minute,@start,@end);
select cast(@difference/60/24 as nvarchar(5)) + case when @difference/60/24 = 1 then ' Day, ' else ' Days, ' end
+ cast(@difference/60%24 as nvarchar(5)) + case when @difference/60%24 = 1 then ' Hour, ' else ' Hours, ' end
+ cast(@difference%60 as nvarchar(5)) + case when @difference%60 = 1 then ' Minute' else ' Minutes' end;
返回:400 Days, 6 Hours, 7 Minutes
当然,如果您只想要 hh:mm
中的小时和分钟格式并且非常有信心这个时差永远不会超过 23 小时 59 分 59.9999999 秒,您可以通过将差异添加到任意日期并在前端应用程序中相应地格式化来简单地将差异转换为时间值:
cast(dateadd(minute,@difference,0) as time)
返回:06:07:00.0000000
对于上述参数 - 请注意缺少的 400 天。
关于SQL门访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40930211/