并发用户报告
Posted
技术标签:
【中文标题】并发用户报告【英文标题】:Concurrent User Report 【发布时间】:2013-10-28 15:53:38 【问题描述】:我在 Oracle 中有一个跟踪用户登录和注销/超时的表。我正在进行选择查询,以按小时显示过去 7 天的并发用户数。我有一个基本查询,但它没有正确计算会话超过午夜的用户。
关于数据/我的查询的一些信息:
Logintracking 保存所有用户登录操作,例如登录/注销/超时操作。每个操作都位于单独的行中。Attemptdate
是动作发生的时间
Attemptresult7
是登录操作的结果(LOGIN/LOGOUT/TIMEOUT)
Maxsessionuid
是用户会话 id,可用于将登录与注销/超时联系起来。
我正在使用左外自连接来匹配登录和基于会话 ID 的注销。由于用户可能仍处于登录状态,因此我将空注销日期替换为 sysdate。
我按年/月/日对数据进行分组,并删除用户可能以不同方式登录两次的所有记录。在此报告中,同一用户登录 10 次仅被视为 1 个并发用户。 (这部分也没有真正起作用,因为我的不同之处在于登录和注销时间,会话之间可能会有所不同。我真的需要为同一用户组合重叠会话......)
我通过查看从 0 到 23 的每小时是否介于他们的登录和注销之间来计算并发用户的数量(这当然不适用于跨天的会话)
--到目前为止我的 Oracle 查询:
Select Lyear,
Lmonth,
Lday,
Sum(Case When 0 Between Lhour And Ohour Then 1 Else 0 End) H00,
Sum(CASE WHEN 1 between LHour and OHour Then 1 Else 0 End) H01,
Sum(CASE WHEN 2 between LHour and OHour Then 1 Else 0 End) H02,
Sum(Case When 3 Between Lhour And Ohour Then 1 Else 0 End) H03,
Sum(CASE WHEN 4 between LHour and OHour Then 1 Else 0 End) H04,
Sum(CASE WHEN 5 between LHour and OHour Then 1 Else 0 End) H05,
Sum(CASE WHEN 6 between LHour and OHour Then 1 Else 0 End) H06,
Sum(CASE WHEN 7 between LHour and OHour Then 1 Else 0 End) H07,
Sum(CASE WHEN 8 between LHour and OHour Then 1 Else 0 End) H08,
Sum(Case When 9 Between Lhour And Ohour Then 1 Else 0 End) H09,
Sum(CASE WHEN 10 between LHour and OHour Then 1 Else 0 End) H10,
Sum(CASE WHEN 11 between LHour and OHour Then 1 Else 0 End) H11,
Sum(CASE WHEN 12 between LHour and OHour Then 1 Else 0 End) H12,
Sum(CASE WHEN 13 between LHour and OHour Then 1 Else 0 End) H13,
Sum(CASE WHEN 14 between LHour and OHour Then 1 Else 0 End) H14,
Sum(CASE WHEN 15 between LHour and OHour Then 1 Else 0 End) H15,
Sum(Case When 16 Between Lhour And Ohour Then 1 Else 0 End) H16,
Sum(Case When 17 Between Lhour And Ohour Then 1 Else 0 End) H17,
Sum(Case When 18 Between Lhour And Ohour Then 1 Else 0 End) H18,
Sum(CASE WHEN 19 between LHour and OHour Then 1 Else 0 End) H19,
Sum(Case When 20 Between Lhour And Ohour Then 1 Else 0 End) H20,
Sum(Case When 21 Between Lhour And Ohour Then 1 Else 0 End) H21,
Sum(CASE WHEN 22 between LHour and OHour Then 1 Else 0 End) H22,
Sum(Case When 23 Between Lhour And Ohour Then 1 Else 0 End) H23
From (
Select Distinct L1.Userid,
Extract(Year From L1.Attemptdate) Lyear,
Extract(Month From L1.Attemptdate) Lmonth,
Extract(Day From L1.Attemptdate) Lday,
--You can't extract HOUR from a date, must be a timestamp
Extract(Hour From Cast(L1.Attemptdate As Timestamp)) As Lhour,
Extract(Hour From Cast(NVL(L2.Attemptdate,SYSDATE) As Timestamp)) As OHour
From Maximo.Logintracking L1
LEFT OUTER JOIN Maximo.Logintracking L2 On
L1.Maxsessionuid = L2.Maxsessionuid
Where L1.Attemptresult7 = 'LOGIN' And L2.Attemptresult7 != 'LOGIN'
And L1.Attemptdate > Trunc( Sysdate)-7
And L2.Attemptdate > Trunc(Sysdate)-7) Sessions
Group By Lyear, Lmonth, Lday
ORDER By LYear, LMonth, LDay
查询不必像现在一样保持不变。但最终结果应该是我按小时查看了 x 天的并发用户数。
相关:How to count the number of concurrent users using time interval data?
【问题讨论】:
【参考方案1】:在此过程中,我写得非常简单整洁的查询变成了这个怪物(似乎有效,所以至少有一件好事):
CREATE TABLE logintracking (
userid NUMBER,
maxsessionuid NUMBER,
Attemptdate DATE,
attemptresult7 VARCHAR2(20)
);
INSERT INTO logintracking VALUES (1, 100, TO_DATE('27-10-2013 10:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGIN');
INSERT INTO logintracking VALUES (1, 100, TO_DATE('27-10-2013 12:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGOUT');
INSERT INTO logintracking VALUES (1, 101, TO_DATE('27-10-2013 11:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGIN');
INSERT INTO logintracking VALUES (1, 101, TO_DATE('27-10-2013 15:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGOUT');
INSERT INTO logintracking VALUES (1, 102, TO_DATE('27-10-2013 23:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGIN');
INSERT INTO logintracking VALUES (1, 102, TO_DATE('28-10-2013 02:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGOUT');
INSERT INTO logintracking VALUES (1, 103, TO_DATE('27-10-2013 20:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGIN');
INSERT INTO logintracking VALUES (1, 103, TO_DATE('28-10-2013 01:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGOUT');
INSERT INTO logintracking VALUES (2, 104, TO_DATE('27-10-2013 23:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGIN');
INSERT INTO logintracking VALUES (2, 104, TO_DATE('28-10-2013 02:00:00', 'DD-MM-YYYY HH24:MI:SS'), 'LOGOUT');
COMMIT;
WITH
hours_of_last_7_days AS (
SELECT TRUNC(SYSDATE, 'HH24') - numtodsinterval(level, 'HOUR') AS hour_val
FROM dual
CONNECT BY level <= 7 * 24
)
SELECT
lyear,
lmonth,
lday,
SUM(DECODE(lhour, 0, 1, 0)) AS H00,
SUM(DECODE(lhour, 1, 1, 0)) AS H01,
SUM(DECODE(lhour, 2, 1, 0)) AS H02,
SUM(DECODE(lhour, 3, 1, 0)) AS H03,
SUM(DECODE(lhour, 4, 1, 0)) AS H04,
SUM(DECODE(lhour, 5, 1, 0)) AS H05,
SUM(DECODE(lhour, 6, 1, 0)) AS H06,
SUM(DECODE(lhour, 7, 1, 0)) AS H07,
SUM(DECODE(lhour, 8, 1, 0)) AS H08,
SUM(DECODE(lhour, 9, 1, 0)) AS H09,
SUM(DECODE(lhour, 10, 1, 0)) AS H10,
SUM(DECODE(lhour, 11, 1, 0)) AS H11,
SUM(DECODE(lhour, 12, 1, 0)) AS H12,
SUM(DECODE(lhour, 13, 1, 0)) AS H13,
SUM(DECODE(lhour, 14, 1, 0)) AS H14,
SUM(DECODE(lhour, 15, 1, 0)) AS H15,
SUM(DECODE(lhour, 16, 1, 0)) AS H16,
SUM(DECODE(lhour, 17, 1, 0)) AS H17,
SUM(DECODE(lhour, 18, 1, 0)) AS H18,
SUM(DECODE(lhour, 19, 1, 0)) AS H19,
SUM(DECODE(lhour, 20, 1, 0)) AS H20,
SUM(DECODE(lhour, 21, 1, 0)) AS H21,
SUM(DECODE(lhour, 22, 1, 0)) AS H22,
SUM(DECODE(lhour, 23, 1, 0)) AS H23
FROM (
SELECT
DISTINCT
sessions.userid,
EXTRACT(YEAR FROM hour_val) AS lyear,
EXTRACT(MONTH FROM hour_val) AS lmonth,
EXTRACT(DAY FROM hour_val) AS lday,
EXTRACT(HOUR FROM CAST(hour_val AS TIMESTAMP)) AS lhour
FROM (
SELECT start_lt.userid, start_lt.attemptdate AS login_date, NVL(end_lt.attemptdate, sysdate) AS logout_date
FROM
logintracking start_lt
LEFT OUTER JOIN logintracking end_lt ON (start_lt.maxsessionuid = end_lt.maxsessionuid AND start_lt.attemptresult7 <> end_lt.attemptresult7)
WHERE
start_lt.attemptresult7 = 'LOGIN'
AND start_lt.attemptdate > Trunc(SYSDATE) - 8
) sessions
JOIN hours_of_last_7_days hd ON (hd.hour_val BETWEEN trunc(sessions.login_date,'HH24') AND trunc(sessions.logout_date,'HH24'))
)
GROUP BY lyear, lmonth, lday
ORDER BY lyear, lmonth, lday
;
输出:
LYEAR LMONTH LDAY H00 H01 H02 H03 H04 H05 H06 H07 H08 H09 H10 H11 H12 H13 H14 H15 H16 H17 H18 H19 H20 H21 H22 H23 ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 2013 10 27 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 2 2013 10 28 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
【讨论】:
非常感谢。我将 Hours_Of_Last_7_days 更改为使用 TRUNC(SYSDATE,'DDD'),我还将内部选择更改为使用 Trunc(SYSDATE,'DDD') - 8 而不是 -7,因为它会切断在午夜之前开始的登录会话第一天,但在午夜后结束。以上是关于并发用户报告的主要内容,如果未能解决你的问题,请参考以下文章