SQL门访问

时间:2016-12-02 10:38:41

标签: sql sql-server database

我对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)

可以访问每个入口和出口。任何帮助都将受到高度赞赏。

由于

1 个答案:

答案 0 :(得分:1)

如果这不仅仅是一次性报告,您几乎肯定需要调整where子句,但对于这两个日期之间的所有EventTime,此查询将为您提供第一个和最后一个每个用户EventTime以及分钟之间的时间。

如果你需要通过特定的flors进一步解决这个问题,你可以将where字段重新添加到select中(虽然我建议不要使用该名称,因为它是一个SQL关键字) }和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事件,然后检查这些事件是否有意义。

您可以从minmax这样的聚合中“排除”某些行,并使用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天。