2013-10-28 23 views
0

我在Oracle中有一個跟蹤用戶登錄和註銷/超時的表。我正在做一個選擇查詢來顯示過去7天內每小時的併發用戶數。我有一個基本查詢,但它不能正確計算會話跨越午夜的用戶。的信息對數據併發用戶報告

位/我的查詢:

  • Logintracking保存所有用戶的登錄操作,如登錄/註銷/超時行爲。每個操作都在單獨的行上。
  • Attemptdate是當動作發生
  • Attemptresult7是登錄操作(登錄/註銷/ 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
+0

謝謝了。我將Hours_Of_Last_7_days更改爲使用TRUNC(SYSDATE,'DDD'),我還將內部選擇更改爲使用Trunc(SYSDATE,'DDD') - 8而不是-7,因爲它切斷了在第一天,但​​在午夜後結束。 – Peter