SQL Server:避免重复行的窗口函数

SQL Server:避免重复行的窗口函数,sql,sql-server,Sql,Sql Server,我需要你的帮助,请帮我解决下面的问题。我在SQL Server数据库中有数据,显示用户是否登录了安全系统 数据结构如下所示: id SystemId Time PC User Logged ----------------------------------------------- 1 2 20171025 16:01 1 John In 2 2 20171025 17:41 4 Mike In 3

我需要你的帮助,请帮我解决下面的问题。我在SQL Server数据库中有数据,显示用户是否登录了安全系统

数据结构如下所示:

id SystemId    Time         PC   User   Logged
-----------------------------------------------
1    2      20171025 16:01   1   John    In
2    2      20171025 17:41   4   Mike    In
3    2      20171025 17:58   1   John    Out
4    2      20171025 17:58   4   Mike    Out
5    2      20171025 19:21   4   Peter   In
6    2      20171025 21:45   4   Peter   In
7    2      20171025 22:59   4   Peter   Out
我需要开发一个脚本,每30分钟运行一次,并且必须显示何时没有用户登录安全监控系统

下面的脚本执行此任务,但有系统/网络问题的情况除外,用户被强制注销并再次登录,而数据库中没有记录强制注销。i、 e.第6行中未记录用户注销,而只记录了已登录的用户

这意味着,当我昨天23:30运行脚本检查Peter(在本例中)是否已登录并执行其工作时,结果显示Peter已登录,而实际上他未登录。(见第6行)

我相信我的解决方案是一个窗口函数(分区依据),它跳过列(PC、用户、日志)中具有相同值的任何连续行。这样我就避免了重复计算。但我不知道我的方向是否正确

SELECT 
    SystemId,
    SUM(CASE
           WHEN Logged = 'In' THEN 1
           WHEN Logged = 'Out' THEN -1
           ELSE 0
        END) AS Connected
FROM 
    log.SecurityLogs
GROUP BY 
    SystemId
HAVING 
    SUM(CASE
           WHEN Logged = 'In' THEN 1
           WHEN Logged = 'Out' THEN -1
           ELSE 0
        END) = 0

用户的状态在
In
Out
之间变化。根据您的描述,不存在嵌套状态(即,您不会期望In-->In-->Out-->Out)

因此,只需比较最大时间:

select sl.SystemId,
       max(case when logged = 'In' then time end) as in_time,
       max(case when logged = 'Out' then time end) as out_time
from log.SecurityLogs sl
group by sl.SystemId;
如果您想要最近事件为“in”的人,则:


谢谢林诺夫先生,你又一次救了我。非常感谢您的帮助和时间。你的建议果然奏效了。
select sl.SystemId,
       max(case when logged = 'In' then time end) as in_time,
       max(case when logged = 'Out' then time end) as out_time
from log.SecurityLogs sl
group by sl.SystemId
having max(case when logged = 'In' then time end) > max(case when logged = 'Out' then time end);