SQL每小时​​最多并发会话数

时间:2014-12-30 10:52:39

标签: sql sql-server-2005

我在医疗保健呼叫中心环境中工作。我可以访问我们的核心系统的数据库,我想使用其中的数据来确定在给定时间内每小时记录的人员数量,可能会超过24小时(例如24/12/2014 - 26 /二千零十四分之十二)。

有一个 userlog 表,用于记录用户登录和注销的时间。

用户日志表格示例

UserRef                                 Date                    LogType SessionID   
--------------------------------------- ----------------------- ------  -----------------------
96AD647C-D061-43F5-9F8D-FA6C74817E07    2002-10-17 14:11:25.763 LOGON   8D451569-0260-46BB-9B9E-F49B3E778161    
96AD647C-D061-43F5-9F8D-FA6C74817E07    2002-10-17 18:11:32.547 LOGOFF  8D451569-0260-46BB-9B9E-F49B3E778161    
60738820-5F72-4E20-A070-57E07C83B6DE    2002-10-17 14:53:31.153 LOGON   C773894C-8B2D-4054-A550-3F04B4C5669F    
60738820-5F72-4E20-A070-57E07C83B6DE    2002-10-17 22:55:25.607 LOGOFF  C773894C-8B2D-4054-A550-3F04B4C5669F
90A55FDD-967E-4D99-96DF-96840CDB2CDF    2002-10-17 15:26:40.123 LOGON   1CE5F5A5-4E20-4D4A-BB67-EB0CB33976D7    
96AD647C-D061-43F5-9F8D-FA6C74817E07    2002-10-17 15:51:28.590 LOGON   7EFDEE1C-15CF-4DE1-B59F-7AFC49B4BE73    
90A55FDD-967E-4D99-96DF-96840CDB2CDF    2002-10-17 15:58:05.217 LOGOFF  1CE5F5A5-4E20-4D4A-BB67-EB0CB33976D7    
96AD647C-D061-43F5-9F8D-FA6C74817E07    2002-10-17 15:58:31.013 LOGOFF  7EFDEE1C-15CF-4DE1-B59F-7AFC49B4BE73    
90A55FDD-967E-4D99-96DF-96840CDB2CDF    2002-10-17 15:58:32.733 LOGON   03F56AB8-FED5-4CC7-8445-26BF55F58E60    
90A55FDD-967E-4D99-96DF-96840CDB2CDF    2002-10-17 16:13:02.827 LOGOFF  03F56AB8-FED5-4CC7-8445-26BF55F58E60    

期望的结果 (这不是为了反映上面的示例数据):

Date         Hour    Number of users logged in
----         ----    -------------------------
01/12/2014    0                   0
01/12/2014    1                   0
01/12/2014    2                   0 
01/12/2014    3                   0
01/12/2014    4                   0
01/12/2014    5                   1
01/12/2014    6                   1
01/12/2014    7                   1
01/12/2014    8                   3
01/12/2014    9                   7
01/12/2014    10                  7
...                 
01/12/2014    23                  0

要清楚:当没有用户登录时,我正试图让小时仍以0计数显示。

我想我正在寻找的是一天中每小时的最大并发会话数,但我并不是过于技术或熟练的SQL(尽管一点一点地变得越来越好!)所以我希望术语不会不要混淆!

我已经搜索过这个并发现了一些类似的场景,但对于Oracle和MySQL,或者日志表以不同方式记录登录数据的情况。我确信我能够成功地将其他数据库查询代码“翻译”为MS SQL,但我还没有!

我正在使用: Microsoft SQL Server 2005 - 9.00.1399.06(Intel X86)。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

更新(第4版)

我在查询结尾处添加了日期过滤器 - WHERE A.[Date] Between @X and @Y - 在这种情况下,它不是最有效的方式,但我认为最简单,启动时不易出错:

SELECT
  A.[Date],
  A.[Hour],
  SUM(CASE WHEN (B.[SessionID] IS NULL) THEN 0 ELSE 1 END) AS [Number_of_Sessions_Per_Hour]
FROM
(
    SELECT DISTINCT
        CONVERT(DATETIME,
            LTRIM(RTRIM(CONVERT(NVARCHAR(10), YEAR(userlog.[Date]))))
            + '-' + RIGHT('0' + LTRIM(RTRIM(CONVERT(NVARCHAR(10), MONTH(userlog.[Date])))), 2)
            + '-' + RIGHT('0' + LTRIM(RTRIM(CONVERT(NVARCHAR(10), DAY(userlog.[Date])))), 2)
            , 120) AS [Date],
        hours_table.[Hour]
    FROM
        userlog,
        (
            SELECT 1 AS [Hour] UNION ALL SELECT 3 AS [Hour] UNION ALL SELECT 4 AS [Hour] UNION ALL SELECT 5 AS [Hour] UNION ALL SELECT 6 AS [Hour]
             UNION ALL SELECT 7 AS [Hour] UNION ALL SELECT 7 AS [Hour] UNION ALL SELECT 8 AS [Hour] UNION ALL SELECT 9 AS [Hour] UNION ALL SELECT 10 AS [Hour]
             UNION ALL SELECT 11 AS [Hour] UNION ALL SELECT 12 AS [Hour] UNION ALL SELECT 13 AS [Hour] UNION ALL SELECT 14 AS [Hour] UNION ALL SELECT 15 AS [Hour]
             UNION ALL SELECT 16 AS [Hour] UNION ALL SELECT 17 AS [Hour] UNION ALL SELECT 18 AS [Hour] UNION ALL SELECT 19 AS [Hour] UNION ALL SELECT 20 AS [Hour]
             UNION ALL SELECT 21 AS [Hour] UNION ALL SELECT 22 AS [Hour] UNION ALL SELECT 23 AS [Hour] UNION ALL SELECT 24 AS [Hour] 
        ) as hours_table
) AS A
LEFT OUTER JOIN
(
    SELECT 
        userlog.SessionID,
        MAX(CASE WHEN userlog.LogType = 'LOGON' 
                 THEN CONVERT(DATETIME,
                        LTRIM(RTRIM(CONVERT(NVARCHAR(10), YEAR(userlog.[Date]))))
                        + '-' + RIGHT('0' + LTRIM(RTRIM(CONVERT(NVARCHAR(10), MONTH(userlog.[Date])))), 2)
                        + '-' + RIGHT('0' + LTRIM(RTRIM(CONVERT(NVARCHAR(10), DAY(userlog.[Date])))), 2)
                        , 120)
                 ELSE CONVERT(DATETIME, '1900-01-01', 120)
            END) AS [Date_Session_START],
        MAX(CASE WHEN userlog.LogType = 'LOGOFF' 
                 THEN CONVERT(DATETIME,
                        LTRIM(RTRIM(CONVERT(NVARCHAR(10), YEAR(userlog.[Date]))))
                        + '-' + RIGHT('0' + LTRIM(RTRIM(CONVERT(NVARCHAR(10), MONTH(userlog.[Date])))), 2)
                        + '-' + RIGHT('0' + LTRIM(RTRIM(CONVERT(NVARCHAR(10), DAY(userlog.[Date])))), 2)
                        , 120)
                 ELSE CONVERT(DATETIME, '1900-01-01', 120)
            END) AS [Date_Session_END],
        MAX(CASE WHEN userlog.LogType = 'LOGON' THEN DATEPART(HOUR, userlog.[Date]) ELSE 0 END) AS [Hour_Session_START],
        MAX(CASE WHEN userlog.LogType = 'LOGOFF' THEN DATEPART(HOUR, userlog.[Date]) ELSE 0 END) AS [Hour_Session_END],
    FROM
        userlog
    GROUP BY
        userlog.SessionID
) AS B
    ON (A.[Date] >= B.[Date_Session_START] AND A.[Date] <= B.[Date_Session_END])
        AND (A.[Hour] >= B.[Hour_Session_START] AND A.[Hour] <= B.[Hour_Session_END])
WHERE
    A.[Date] Between @X and @Y
GROUP BY
  A.[Date],
  A.[Hour]

答案 1 :(得分:0)

好的,采取了稍微不同的方法。我构建了一个Logon / Log Off表 - 这可能是一个cte但我不是oracle专家,因此不确定它是否支持更简单的SQL和临时表。我已经建立了一个静态整数表(也称为计数表)0-30,根据你上面的答案在我的查询中处理测试日期范围 - 如果你有一个已经可以使用那个范围下来并保存一些努力。运行查询会返回一个这样的表(使用下面的示例数据)

StartDate   WorkingHour LoggedInUsers
2002-10-17 00:00:00.000 10  0
2002-10-17 00:00:00.000 11  0
2002-10-17 00:00:00.000 12  0
2002-10-17 00:00:00.000 13  0
2002-10-17 00:00:00.000 14  2
2002-10-17 00:00:00.000 15  5
2002-10-17 00:00:00.000 16  3
2002-10-17 00:00:00.000 17  2
2002-10-17 00:00:00.000 18  2
2002-10-17 00:00:00.000 19  1
2002-10-17 00:00:00.000 20  1
2002-10-17 00:00:00.000 21  1
2002-10-17 00:00:00.000 22  1
2002-10-17 00:00:00.000 23  0

代码在sql中运行

DECLARE @StartDate DATETIME ,
@NoDays INT ;


select
@StartDate = '2002-10-01',
@NoDays = 20;



DECLARE @Sessions TABLE (
UserRef UNIQUEIDENTIFIER,
DATE DATETIME,
LogType VARCHAR(100), 
SessionID UNIQUEIDENTIFIER
);
INSERT INTO @Sessions
SELECT '96AD647C-D061-43F5-9F8D-FA6C74817E07', '2002-10-17 14:11:25.763', 'LOGON', '8D451569-0260-46BB-9B9E-F49B3E778161'
UNION SELECT '96AD647C-D061-43F5-9F8D-FA6C74817E07', '2002-10-17 18:11:32.547', 'LOGOFF', '8D451569-0260-46BB-9B9E-F49B3E778161'
UNION SELECT '60738820-5F72-4E20-A070-57E07C83B6DE', '2002-10-17 14:53:31.153', 'LOGON', 'C773894C-8B2D-4054-A550-3F04B4C5669F'
UNION SELECT '60738820-5F72-4E20-A070-57E07C83B6DE', '2002-10-17 22:55:25.607', 'LOGOFF', 'C773894C-8B2D-4054-A550-3F04B4C5669F'
UNION SELECT '90A55FDD-967E-4D99-96DF-96840CDB2CDF', '2002-10-17 15:26:40.123', 'LOGON', '1CE5F5A5-4E20-4D4A-BB67-EB0CB33976D7'
UNION SELECT '96AD647C-D061-43F5-9F8D-FA6C74817E07', '2002-10-17 15:51:28.590', 'LOGON', '7EFDEE1C-15CF-4DE1-B59F-7AFC49B4BE73'
UNION SELECT '90A55FDD-967E-4D99-96DF-96840CDB2CDF', '2002-10-17 15:58:05.217', 'LOGOFF', '1CE5F5A5-4E20-4D4A-BB67-EB0CB33976D7'
UNION SELECT '96AD647C-D061-43F5-9F8D-FA6C74817E07', '2002-10-17 15:58:31.013', 'LOGOFF', '7EFDEE1C-15CF-4DE1-B59F-7AFC49B4BE73'
UNION SELECT '90A55FDD-967E-4D99-96DF-96840CDB2CDF', '2002-10-17 15:58:32.733', 'LOGON', '03F56AB8-FED5-4CC7-8445-26BF55F58E60'
UNION SELECT '90A55FDD-967E-4D99-96DF-96840CDB2CDF', '2002-10-17 16:13:02.827', 'LOGOFF', '03F56AB8-FED5-4CC7-8445-26BF55F58E60';  


DECLARE @staticintegers TABLE (myInteger INT);
INSERT INTO @staticintegers 
SELECT 0 UNION SELECT 1  UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8
UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12 UNION SELECT 13
UNION SELECT 14 UNION SELECT 15 UNION SELECT 16 UNION SELECT 17 UNION SELECT 18
UNION SELECT 19 UNION SELECT 20 UNION SELECT 21 UNION SELECT 22 UNION SELECT 23
UNION SELECT 24 UNION SELECT 25 UNION SELECT 26 UNION SELECT 27 UNION SELECT 28
UNION SELECT 29 UNION SELECT 30 UNION SELECT 31 UNION SELECT 32 UNION SELECT 33;

DECLARE @sessionsOutput TABLE (SessionID UNIQUEIDENTIFIER, StartTime DATETIME, EndTime DATETIME);
INSERT INTO @sessionsOutput
(SessionID, StartTime)
SELECT 
    SessionID,
    [date]
FROM 
    @Sessions
    WHERE logtype = 'Logon';

UPDATE @sessionsOutput
SET EndTime = [date]
FROM @sessionsOutput aa
INNER JOIN @Sessions bb
ON aa.SessionID = bb.SessionID
WHERE bb.LogType = 'Logoff';



SELECT
    DATEADD(dd, DateIntegers.myInteger, @StartDate) AS StartDate
    ,hoursintegers.myINteger AS WorkingHour
    ,COUNT(aa.SessionID) AS LoggedInUsers


FROM 
    @staticintegers DateIntegers
    LEFT OUTER JOIN @StaticIntegers HoursIntegers
    ON HoursIntegers.myInteger BETWEEN 0 AND 23

LEFT OUTER JOIN @sessionsOutput aa
ON
    HoursIntegers.myInteger BETWEEN DATEPART(hh, aa.StartTime) AND DATEPART(hh, aa.endtime)
    AND CAST(aa.StartTime AS DATE) = DATEADD(dd, dateintegers.myInteger, @StartDate) 

GROUP BY 
    DATEADD(dd, DateIntegers.myInteger, @StartDate),
    HoursIntegers.myInteger
ORDER BY 
    DATEADD(dd, DateIntegers.myInteger, @StartDate),
    HoursIntegers.myInteger;