1、源數據表結構、樣例數據及說明
CREATE TABLE `karaoke_room_actor_snapshot_0` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`actor_id` bigint(20) NOT NULL COMMENT '演員 ID',
`room_id` int(11) NOT NULL COMMENT '直播間 ID',
`live_status_id` int(11) NOT NULL COMMENT '直播狀態 ID',
`uid` bigint(20) NOT NULL COMMENT '表演者 Uid',
`music_id` int(11) NOT NULL DEFAULT '-1' COMMENT '伴奏 ID',
`identifier` varchar(190) NOT NULL DEFAULT '' COMMENT '設備號',
`score` bigint(20) NOT NULL DEFAULT '0' COMMENT '積分,輔助排序',
`state` tinyint(4) NOT NULL DEFAULT '0' COMMENT '狀態:0排麥中,1準備中,2表演中,-1表演結束,-2主動下麥,-3房主強制下麥,-4系統強制下麥',
`created_time` datetime(6) NOT NULL COMMENT '創建時間',
PRIMARY KEY (`id`),
KEY `Index_roomId_lsId_uid` (`room_id`,`live_status_id`,`uid`),
KEY `idx_actor_created` (`actor_id`,`created_time`),
KEY `idx_room_live_state` (`room_id`,`live_status_id`,`state`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='麥序演員快照,按 room_id 256分表'
id actor_id room_id live_status_id uid music_id identifier score state created_time
1 728 37194071 292 200134 62348 889134744 1531137151093 0 2018-07-09 19:52:31.000000
2 728 37194071 292 200134 62348 889134744 1531137151093 1 2018-07-09 19:52:33.000000
3 728 37194071 292 200134 62348 889134744 1531137151093 -3 2018-07-09 19:52:52.000000
4 729 37194071 292 200134 26081 889134744 1531137204230 0 2018-07-09 19:53:24.000000
5 729 37194071 292 200134 26081 889134744 1531137204230 1 2018-07-09 19:53:26.000000
6 729 37194071 292 200134 26081 889134744 1531137204230 -3 2018-07-09 19:53:44.000000
7 730 37194071 292 200134 26081 889134744 1531137395308 0 2018-07-09 19:56:35.000000
8 730 37194071 292 200134 26081 889134744 1531137395308 1 2018-07-09 19:56:38.000000
9 730 37194071 292 200134 26081 889134744 1531137395308 2 2018-07-09 19:56:45.000000
10 731 37194071 292 200119 84874 BBA67879-E1FB-4B0E-82E6-3841D8301EB2 1531137444615 0 2018-07-09 19:57:24.000000
11 732 37194071 292 330451222 114810 379085366 1531137497910 0 2018-07-09 19:58:17.000000
12 732 37194071 292 330451222 114810 379085366 1531137497910 -2 2018-07-09 19:58:38.000000
13 730 37194071 292 200134 26081 889134744 1531137395308 -3 2018-07-09 19:59:52.000000
說明:
用戶進入、等待、退出等分別有一條記錄;一個用戶可以多次進行同一個房間;沒有標記其哪幾條(進入、退出)是同一次,只是根據靠近的時間來判斷;現在要求根據豎狀表整成橫行表,計算出用戶的表演時間、等待時間等。
2、問題分析及思路說明
從數據上觀察,用戶可以沒有準備中及表演中的記錄,但一定會有排麥中及退出(小於0)的記錄。可以由此排名確定同一次,然後根據時間範圍鎖定其其他活動記錄。
所以,先進行用戶數據排名,之後進行其他數據的相關計算。
3、具體sql語句
爲更好的清晰思路,主要採用多臨時表的方式進行處理。
drop table if exists xxxlv_mic_range;
create table xxxlv_mic_range as
with tab_mic_start as (
select pt_day,room_id,uid,state,created_time,row_number()over(partition by room_id,uid order by created_time asc) mic_start_rn
from oss_all_karaoke_room_actor_snapshot
where pt_day between '2018-07-18' and '2018-07-26'
and state=0),
tab_mic_over as (
select pt_day,room_id,uid,state,created_time,row_number()over(partition by room_id,uid order by created_time asc) mic_over_rn
from oss_all_karaoke_room_actor_snapshot
where pt_day between '2018-07-18' and '2018-07-26'
and state<0)
select a1.pt_day,a1.room_id,a1.uid,a1.created_time mic_start_time,a2.created_time mic_over_time,a1.mic_start_rn
from tab_mic_start a1
left join tab_mic_over a2 on a1.pt_day=a2.pt_day and a1.room_id=a2.room_id and a1.uid=a2.uid and a1.mic_start_rn=a2.mic_over_rn;
drop table if exists xxxlv_mic_ready;
create table xxxlv_mic_ready as
select a1.pt_day,a1.room_id,a1.uid,a1.state,a1.created_time ready_time,a2.mic_start_time,a2.mic_over_time
from oss_all_karaoke_room_actor_snapshot a1
inner join xxxlv_mic_range a2 on a1.pt_day=a2.pt_day and a1.room_id=a2.room_id and a1.uid=a2.uid
where a1.pt_day between '2018-07-18' and '2018-07-26'
and a1.state=1
and a1.created_time between a2.mic_start_time and a2.mic_over_time;
drop table if exists xxxlv_mic_runing;
create table xxxlv_mic_runing as
select a1.pt_day,a1.room_id,a1.uid,a1.state,a1.created_time runing_time,a2.mic_start_time,a2.mic_over_time
from oss_all_karaoke_room_actor_snapshot a1
inner join xxxlv_mic_range a2 on a1.pt_day=a2.pt_day and a1.room_id=a2.room_id and a1.uid=a2.uid
where a1.pt_day between '2018-07-18' and '2018-07-26'
and a1.state=2
and a1.created_time between a2.mic_start_time and a2.mic_over_time;
drop table if exists xxxlv_mic_basic;
create table xxxlv_mic_basic as
select a0.pt_day,a0.room_id,a0.uid,a0.mic_start_time,a1.ready_time,a2.runing_time,a0.mic_over_time
from xxxlv_mic_range a0
left join xxxlv_mic_ready a1 on a0.pt_day=a1.pt_day and a0.room_id=a1.room_id and a0.uid=a1.uid and a0.mic_start_time=a1.mic_start_time and a0.mic_over_time=a1.mic_over_time
left join xxxlv_mic_runing a2 on a0.pt_day=a2.pt_day and a0.room_id=a2.room_id and a0.uid=a2.uid and a0.mic_start_time=a2.mic_start_time and a0.mic_over_time=a2.mic_over_time
;
drop table if exists xxxlv_mic_timelog;
create table xxxlv_mic_timelog as
select a1.pt_day,a1.uid,a3.nickname,a1.room_id,a1.runing_time,a1.mic_over_time,(unix_timestamp(a1.mic_over_time)-unix_timestamp(coalesce(a1.runing_time,a1.mic_over_time)))/60 act_times,(unix_timestamp(coalesce(a1.runing_time,a1.mic_over_time))-unix_timestamp(a1.mic_start_time))/60 wait_times,a1.mic_start_time
from xxxlv_mic_basic a1
inner join xxxlv_user_info a2 on a1.room_id=a2.room_id
left join (select uid,nickname from oss_bi_all_user_profile where pt_day='2018-07-22') a3 on a1.uid=a3.uid;
drop table if exists xxxlv_gift_record_info21;
create table xxxlv_gift_record_info21 as
select a1.pt_day,a1.receive_uid,a1.room_id,a2.mic_start_time,a2.mic_over_time,sum(case when a1.source=1 then a1.gift_count else 0 end) rechargeable_cnt,sum(case when a1.source=2 then a1.gift_count else 0 end) free_cnt,sum(a1.gift_count) all_cnt
from oss_all_karaoke_gift_record a1
left join (select a1.pt_day,a1.uid,a1.nickname,a1.room_id,a1.runing_time,a1.mic_over_time,a1.mic_start_time
from xxxlv_mic_timelog a1
where a1.runing_time is not null) a2 on a1.pt_day=a2.pt_day and a1.receive_uid=a2.uid and a1.room_id=a2.room_id
where a1.pt_day between '2018-07-18' and '2018-07-26'
and a1.created_time between a2.runing_time and a2.mic_over_time
group by a1.pt_day,a1.receive_uid,a1.room_id,a2.mic_start_time,a2.mic_over_time
;
-------------------------------------------------------------------------------------------
drop table if exists xxxlv_user_result21;
create table xxxlv_user_result21 as
select a1.pt_day,a1.uid,a1.nickname,a1.room_id,a1.runing_time,a1.mic_over_time,a1.act_times,a1.wait_times,a2.rechargeable_cnt,a2.free_cnt,a2.all_cnt
from xxxlv_mic_timelog a1
left join xxxlv_gift_record_info21 a2 on a1.pt_day=a2.pt_day and a1.uid=a2.receive_uid and a1.room_id=a2.room_id and a1.mic_start_time=a2.mic_start_time and a1.mic_over_time=a2.mic_over_time
;
-------------------------------------------------------------------------------------------
--2.2是2.1的彙總
drop table if exists xxxlv_user_result22;
create table xxxlv_user_result22 as
select a1.pt_day,a1.uid,a1.nickname,a1.room_id,sum(a1.act_times) act_times,sum(a1.wait_times) wait_times,count(*) mic_cnt,count(case when a1.runing_time is not null then a1.uid else null end) act_cnt,
sum(a1.rechargeable_cnt) rechargeable_cnt,sum(a1.free_cnt) free_cnt,sum(a1.all_cnt) all_cnt
from xxxlv_user_result21 a1
group by a1.pt_day,a1.uid,a1.nickname,a1.room_id;