2017-07-31 56 views
1

請耐心等待,我的英文不是很好,插入持續時間長於一個小時到另一個表小時逐小時

我已成立了一個MySQL表彙總登錄到它:

create table logs(
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, 
player_id MEDIUMINT UNSIGNED NOT NULL, 
`in` DATETIME NOT NULL, 
`out` DATETIME NOT NULL, 
channel_id INT UNSIGNED NOT NULL, 
frame_id INT UNSIGNED NOT NULL, 
media_id INT UNSIGNED NOT NULL 
PRIMARY KEY (id) 

我使用inout之間的timediff來找出文件播放的時間以及播放時間。 它成爲一種大的,所以我決定聚集所需要的信息插入到新表:

create table reports(
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, 
year SMALLINT UNSIGNED NOT NULL, 
month TINYINT UNSIGNED NOT NULL, 
day TINYINT UNSIGNED NOT NULL, 
hour TINYINT UNSIGNED NOT NULL, 
player_id MEDIUMINT UNSIGNED NOT NULL, 
channel_id INT UNSIGNED NOT NULL, 
frame_id INT UNSIGNED NOT NULL, 
media_id INT UNSIGNED NOT NULL, 
count MEDIUMINT UNSIGNED NOT NULL, 
duration MEDIUMINT UNSIGNED NOT NULL 

我用下面的查詢來填寫報告表:

insert into reports (year, month, day, hour, player_id, media_id, channel_id, frame_id, count, duration) 
select year(logs.in), month(logs.in) as Month, day(logs.in) as Day, hour(logs.in) as Hour, logs.player_id, logs.media_id, logs.channel_id, logs.frame_id, count(logs.media_id) as Count, SUM(TIME_TO_SEC(TIMEDIFF(logs.out, logs.in))) as Duration 
FROM logs 
where (logs.player_id=1 OR logs.player_id=2) 
GROUP BY year(logs.in), month(logs.in), day(logs.in), hour(logs.in), player_id, media_id, channel_id, frame_id; 

它的工作原理確定,如果timeDiff測量少比一個小時。但是,一個媒體可以超過幾分鐘更多的發揮:

+-------+------+------+-----------+------------+----------+----------+----------------------+--------------+ 
| Month | Day | Hour | player_id | channel_id | frame_id | media_id | count(logs.media_id) | Duration  | 
+-------+------+------+-----------+------------+----------+----------+----------------------+--------------+ 
|  6 | 19 | 14 |   5 |   4 |  18 |  54 |     1 | 275h 48m 24s | 
|  6 | 20 | 8 |   4 |   3 |  18 |  54 |     1 | 78h 45m 28s | 

所以,如果我檢查文件是否於6月玩上player_id 5,20日我的查詢會告訴我這不是,雖然當時。我想要達到的是填寫我的報告表如:

+-------+------+------+-----------+------------+----------+----------+----------------------+--------------+ 
| Month | Day | Hour | player_id | channel_id | frame_id | media_id | count(logs.media_id) | Duration  | 
+-------+------+------+-----------+------------+----------+----------+----------------------+--------------+ 
|  6 | 19 | 14 |   5 |   4 |  18 |  54 |     1 |  48m 24s | 
|  6 | 19 | 15 |   5 |   4 |  18 |  54 |     1 | 1h 00m 00s | 
|  6 | 19 | 16 |   5 |   4 |  18 |  54 |     1 | 1h 00m 00s | 

有沒有辦法?提前致謝。

回答

0

好吧,我發現了一種溶劑。首先,我必須創建一個時間範圍表。我使用存儲過程的舒適

CREATE DEFINER=`root`@`localhost` PROCEDURE `make_intervals`(startdate 
timestamp, enddate timestamp, intval integer, unitval varchar(10)) 
BEGIN 
    declare thisDate timestamp; 
    declare nextDate timestamp; 
    set thisDate = startdate; 
    drop temporary table if exists time_intervals; 
    create temporary table if not exists time_intervals 
    (
    interval_start timestamp, 
    interval_end timestamp 
); 
    repeat 
     select 
     case unitval 
      when 'MICROSECOND' then timestampadd 
(MICROSECOND, intval, thisDate) 
      when 'SECOND'  then timestampadd(SECOND, intval, thisDate) 
      when 'MINUTE'  then timestampadd(MINUTE, intval, thisDate) 
      when 'HOUR'  then timestampadd(HOUR, intval, thisDate) 
      when 'DAY'   then timestampadd(DAY, intval, thisDate) 
      when 'WEEK'  then timestampadd(WEEK, intval, thisDate) 
      when 'MONTH'  then timestampadd(MONTH, intval, thisDate) 
      when 'QUARTER'  then timestampadd(QUARTER, intval, thisDate) 
      when 'YEAR'  then timestampadd(YEAR, intval, thisDate) 
     end into nextDate; 
    insert into time_intervals select thisDate, timestampadd(MICROSECOND, -1, nextDate); 
    set thisDate = nextDate; 
    until thisDate >= enddate 
    end repeat; 

END 

然後我處理我的主表反對這個臨時表

SELECT DATE(time_intervals.interval_start) AS Date, EXTRACT(HOUR FROM time_intervals.interval_start) AS Hour, player_id, channel_id, frame_id, media_id, count(media_id), 
     sum(CASE 
      WHEN time_intervals.interval_start > TIMESTAMPADD(HOUR,HOUR(logs.in), DATE(logs.in)) 
    AND time_intervals.interval_start < TIMESTAMPADD(HOUR,HOUR(logs.out), DATE(logs.out)) 
    THEN 3600 
WHEN time_intervals.interval_start = TIMESTAMPADD(HOUR,HOUR(logs.in), DATE(logs.in)) 
AND time_intervals.interval_start < TIMESTAMPADD(HOUR,HOUR(logs.out), DATE(logs.out)) 
THEN 3600 - EXTRACT(MINUTE FROM logs.in)*60 - EXTRACT(SECOND FROM logs.in) 
WHEN time_intervals.interval_start = TIMESTAMPADD(HOUR,HOUR(logs.out), DATE(logs.out)) 
AND time_intervals.interval_start > TIMESTAMPADD(HOUR,HOUR(logs.in), DATE(logs.in)) 
THEN EXTRACT(SECOND FROM logs.out) + EXTRACT(MINUTE FROM logs.out)*60 
WHEN time_intervals.interval_start = TIMESTAMPADD(HOUR,HOUR(logs.in), DATE(logs.in)) 
AND time_intervals.interval_start = TIMESTAMPADD(HOUR,HOUR(logs.out), DATE(logs.out)) 
THEN EXTRACT(MINUTE FROM logs.out)*60 + EXTRACT(SECOND FROM logs.out) - EXTRACT(MINUTE FROM logs.in)*60 - EXTRACT(SECOND FROM logs.in) 
ELSE 0 
END) AS duration 
FROM time_intervals 
LEFT JOIN logs 
Force index(media_id, player_id, channel_id, frame_id) 
    ON time_intervals.interval_start >= TIMESTAMPADD(HOUR,HOUR(logs.in), DATE(logs.in)) 
    AND time_intervals.interval_start <= TIMESTAMPADD(HOUR,HOUR(logs.out), DATE(logs.out)) 
    GROUP BY media_id, player_id, date, hour, channel_id, frame_id; 

需要一段時間來處理,特別是數十億行的,就像我的情況,但作品。

相關問題