使用聚合自我加入SQL Server

时间:2018-01-26 16:42:03

标签: sql-server self-join

我有一个查询返回当天开始的所有会话,然后给出我自上次登录以来当前活动会话和时间的计数。 (这让我知道是否有任何内核会产生任何导致用户无法登录的问题)

SELECT [server]
     , appserver
     , count(*) as open_sessions
     , max(start_time) Latest_New_Login
     , datediff(minute, max(start_time) , GETDATE() ) elapsed_mins_since_last_login
FROM [session_logs]
where DATEDIFF(day, START_TIME, GETDATE()) <= 0  
and end_time is null
group by server, appserver
order by 1,2

返回数据

+---------+-----------+---------------+-------------------------+-------------------------------+
| server  | appserver | open_sessions |    Latest_New_Login     | Elapsed_mins_since_last_login |
+---------+-----------+---------------+-------------------------+-------------------------------+
| SERVER1 | PK1       |            13 | 2018-01-26 16:24:47.087 |                             1 |
| SERVER1 | PK2       |            12 | 2018-01-26 16:19:00.157 |                             6 |
| SERVER2 | PK1       |             8 | 2018-01-26 16:25:41.297 |                             0 |
| SERVER2 | PK2       |             6 | 2018-01-26 16:07:31.027 |                            18 |
| SERVER3 | PK1       |             7 | 2018-01-26 16:18:56.597 |                             7 |
| SERVER3 | PK2       |             5 | 2018-01-26 16:19:06.550 |                             6 |
+---------+-----------+---------------+-------------------------+-------------------------------+

一切都很好, 但是我需要一种解决方法来确保显示所有服务器和应用服务器。我们今天遇到了一个问题,即服务器3 PK1上没有显示活动登录,这从我的结果表中删除了它的条目。

有没有办法可以让下面的数据集始终显示并让我的聚合函数与它们相符?一个自我加入的查询,但我无法使其正常工作。

select distinct [server], appserver
FROM [session_logs]

返回值

Server 1 PK1
Server 1 PK2
Server 2 PK1
Server 2 PK2
Server 3 PK1
Server 3 PK2

3 个答案:

答案 0 :(得分:0)

执行LEFT JOIN

SELECT
    serv.[server],
    serv.appserver,
    t.open_sessions,
    t.Latest_New_Login,
    t.elapsed_mins_since_last_login
FROM (
    SELECT DISTINCT [server], appserver FROM [session_logs]
) serv
LEFT JOIN (
    SELECT [server]
         , appserver
         , COUNT(*) AS open_sessions
         , MAX(start_time) AS Latest_New_Login
         , DATEDIFF(MINUTE, MAX(start_time), GETDATE()) AS elapsed_mins_since_last_login
    FROM [session_logs]
    WHERE
        DATEDIFF(day, START_TIME, GETDATE()) <= 0  
        AND end_time is null
    GROUP BY [server], appserver
) t
    ON t.[server] = serv.[server]
    AND t.appserver = serv.appserver
ORDER BY
    serv.[server], serv.appserver

如果您有一个包含服务器列表的表,请使用该表而不是:

SELECT DISTINCT [server], appserver FROM [session_logs]

答案 1 :(得分:0)

不使用JOIN

的另一个选项
select
    [server]
    , appserver
    , count(start_time) as open_sessions
    , max(start_time) Latest_New_Login
    , datediff(minute, max(start_time) , GETDATE() ) elapsed_mins_since_last_login
from (
    SELECT [server]
         , appserver
        , start_time
    FROM 
        [session_logs]
    where 
        DATEDIFF(day, START_TIME, GETDATE()) <= 0  
        and end_time is null
    union all select distinct [server], appserver, null FROM [session_logs]
) t
group by server, appserver

答案 2 :(得分:0)

使用所有唯一服务器和LEFT JOIN构建公用表表达式:

;with cte([server], appserver)
as (
    select distinct [server], appserver
    from [session_logs]
    -- let's limit with records from last 30 days in case [session_logs] is a massive table
    -- I assume all servers you care about had some activity in that time
    where DATEDIFF(day, START_TIME, GETDATE()) <= 30
)
SELECT cte.[server]
     , cte.appserver
     , count(start_time) as open_sessions
     , max(start_time) Latest_New_Login
     , datediff(minute, max(start_time), GETDATE()) Elapsed_mins_since_last_login
FROM cte
left join [session_logs] as sl on cte.[server] = sl.[server] and cte.appserver = sl.appserver
where DATEDIFF(day, START_TIME, GETDATE()) <= 0  
and end_time is null
group by cte.[server], cte.appserver
order by cte.[server], cte.appserver