簡體   English   中英

SQL查詢分組日期/時間活動的“塊”?

[英]SQL Query to Group “Blocks” of Date/Time Activity?

我在表中有數據,這是服務器活動的日志數據。 這是它的樣子(#列不是數據庫或輸出的一部分,但是我可以在下面的注釋中引用該數據):

# | DateStamp           | Server  
- | ------------------- | ---------  
1 | 2016-12-01 03:15:19 | Server 1
2 | 2016-12-01 03:17:19 | Server 2
3 | 2016-12-01 03:17:24 | Server 2
4 | 2016-12-01 03:18:01 | Server 1
5 | 2016-12-01 03:18:07 | Server 3
6 | 2016-12-01 04:01:03 | Server 3
7 | 2016-12-01 07:18:47 | Server 1
8 | 2016-12-01 07:19:23 | Server 1
9 | 2016-12-01 09:19:39 | Server 2
10| 2016-12-01 11:19:54 | Server 3

我想寫一個輸出的查詢:

# | Server   | Online              | Offline
- | -------- | ------------------- | -------------------
1 | Server 1 | 2016-12-01 03:15:19 | 2016-12-01 03:18:01
2 | Server 2 | 2016-12-01 03:17:19 | 2016-12-01 03:17:24
3 | Server 3 | 2016-12-01 03:18:07 | 2016-12-01 03:18:07
4 | Server 1 | 2016-12-01 07:18:47 | 2016-12-01 07:19:23
5 | Server 2 | 2016-12-01 09:19:39 | 2016-12-01 09:19:39
6 | Server 3 | 2016-12-01 11:19:54 | (still online)

筆記:

  • 這基本上是這些服務器“活躍”和持續多長時間的統計數據。
  • 如果下一個服務器的活動間隔大於一小時,則將其視為新會話並獲取新行。 (即輸出的第1行和第4行,基於上面的數據行4和7)
  • 澄清:輸出的第1行決定03:18:01是“離線”,因為服務器1的下一個條目(數據第7行的07:18:47)超過一個小時。
  • 輸出的第5行顯示為脫機,因為已經過了一個多小時,並且沒有出現服務器2的新條目

我很想知道如何查詢,並根據上面的輸出和注釋對結果進行分組。 如果您需要更多信息來建議解決方案,請與我們聯系。

1)首先,您應該將日志加載到MySQL DB中:

# Optionally
#drop table if exists srv_logs;

create table srv_logs (
        `id` INT(10) NOT NULL AUTO_INCREMENT,
        `datetime` DATETIME ,
        `server` VARCHAR(300),
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOAD DATA INFILE 'yourfile.log'
    INTO TABLE srv_logs
    CHARSET utf8
    FIELDS TERMINATED BY '|'  
    OPTIONALLY ENCLOSED BY '"'   
    LINES TERMINATED BY '\n'  IGNORE 2 LINES (
        `id`,
        `datetime`,
        `server`
    );

2)創建/填充初始數據您的停機時間表:

create table srv_downtime (
        `id` INT(10) NOT NULL AUTO_INCREMENT,
        `server` VARCHAR(300),
        `online` DATETIME ,
        `offline` DATETIME ,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into  srv_downtime (`server`, `online`, `offline`)
SELECT l.server, MAX(l.datetime), null
FROM srv_logs l
left join srv_logs l2 
   on l.server = l2.server 
   and l.datetime > l2.datetime
   and TIMESTAMPDIFF(MINUTE,l2.datetime,l.datetime) < 60
where l2.id is null 
GROUP BY l.server

3)反復調用此插入,直到不添加新行,它將向底部添加新行(前一工作期)

    insert into  srv_downtime (`server`, `online`, `offline`)
    (select a.server, min(l2.datetime), offline from
      (SELECT d.server, max(l.datetime) as offline
         FROM srv_downtime d
         left join srv_logs l 
            on l.server = d.server 
            and d.online > l.datetime
         group by l.server
      ) a
      left join srv_logs l2 
        on a.offline > l2.datetime 
        and l2.server = a.server
        and TIMESTAMPDIFF(MINUTE, l2.datetime, a.offline) < 60
      group by a.server
   )

因此,在這3個步驟之后的示例數據集上,結果似乎是正確的:

Server 1  | 2016-12-01 03:15:19 | 2016-12-01 03:18:01
Server 1  | 2016-12-01 07:18:47 | NULL
Server 2  | 2016-12-01 03:17:19 | 2016-12-01 03:17:24
Server 2  | 2016-12-01 09:19:39 | NULL
Server 3  | 2016-12-01 03:18:07 | 2016-12-01 04:01:03
Server 3  | 2016-12-01 11:19:54 | NULL

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM