【SQL】 瞬时在线用户数

题目

牛客网——SQL179:各城市最大同时等车人数

题目描述

问题:统计各个城市在2021年10月期间,单日中最大的同时等车人数。

数据:

用户打车记录表tb_get_car_record

iduidcityevent_timeend_timeorder_id
1108北京2021-10-20 08:00:002021-10-20 08:00:409008
2118北京2021-10-20 08:00:102021-10-20 08:00:459018
3102北京2021-10-20 08:00:302021-10-20 08:00:509002
4106北京2021-10-20 08:05:412021-10-20 08:06:009006
5103北京2021-10-20 08:05:502021-10-20 08:07:109003
6104北京2021-10-20 08:01:012021-10-20 08:01:209004
7105北京2021-10-20 08:01:152021-10-20 08:01:309019
8101北京2021-10-20 08:28:102021-10-20 08:30:009011

打车订单表tb_get_car_order

idorder_iduiddriver_idorder_timestart_timefinish_timemileagefaregrade
190081082042021-10-20 08:00:402021-10-20 08:03:002021-10-20 08:31:0013.2384
290181082142021-10-20 08:00:452021-10-20 08:04:502021-10-20 08:21:0014385
390021022022021-10-20 08:00:502021-10-20 08:06:002021-10-20 08:31:001041.55
490061062062021-10-20 08:06:002021-10-20 08:09:002021-10-20 08:31:00825.54
590031032032021-10-20 08:07:102021-10-20 08:15:002021-10-20 08:31:001141.54
690041042042021-10-20 08:01:202021-10-20 08:13:002021-10-20 08:31:007.5224
790191052052021-10-20 08:01:302021-10-20 08:11:002021-10-20 08:51:0010394
890111012112021-10-20 08:30:002021-10-20 08:31:002021-10-20 08:54:0010355

求解思路

这是一道典型的求解同时在线用户数量的题目,与“统计直播间在线用户数”的逻辑一致。

  • 瞬时UV的计算方法:进入事件记作UV=1,离开事件记作UV=-1,使用窗口函数SUM(uv)OVER(ORDER BY 事件,uv DESC)进行累加

首先,需要对用户进入和离开的形式进行定义。

进入时间:event_time,开始打车的时间即为等车开始。

离开时间:有3种情况

  • 状态1:司机接单前取消,则没有生成order_id,这种情况 order_id IS NULL 记录end_time
  • 状态2:司机接单后取消,则没有上车时间,start_time IS NULL 记录 finish_time
  • 状态3:正常上车,记录start_time,start_time IS NOT NULL
  • 状态2和3可以直接使用IFNULL()合并,IFNULL(start_time,finish_time) 如果start_time空则返回finish_time,不空则start_time

定义完用户进入等车和离开等车这两种事件之后,关联所有表格,使用窗口函数排序累加即可。

现求出这三种情况的数据如下:

  • uv为1,用户进入打车状态
SELECT city,event_time uv_time,1 AS uv FROM tb_get_car_record
  • uv为-1,状态1:司机接单前取消,则没有生成order_id,这种情况 order_id IS NULL 记录end_time
SELECT city,end_time uv_time,-1 AS uv FROM  tb_get_car_record WHERE order_id IS NULL #接单前取消
  • uv为-1,状态2:接单后取消或者用户正常上车
SELECT city,IFNULL(start_time,finish_time) uv_time,-1 AS uv FROM tb_get_car_order LEFT JOIN tb_get_car_record USING(order_id) #接单后取消或上车
  • 建立子表:使用union all 全关联
SELECT city,event_time uv_time,1 AS uv FROM  tb_get_car_record 
UNION ALL
SELECT city,end_time uv_time,-1 AS uv FROM  tb_get_car_record WHERE order_id IS NULL #接单前取消
UNION ALL
SELECT city,IFNULL(start_time,finish_time) uv_time,-1 AS uv FROM tb_get_car_order LEFT JOIN tb_get_car_record USING(order_id)#接单后取消或上车

这里可以得到每个城市的uv_time和uv数值如下:

之后统计2021年10月,每个城市的瞬时UV情况,并取出每个城市最大的UV,排序先按照uv升序,uv一样按照城市升序

SELECT
    city,
    MAX(uv_cnt) max_wait_uv 
FROM
(
    SELECT 
        city,
        SUM(uv)OVER(PARTITION BY city ORDER BY uv_time,uv DESC) AS uv_cnt
    FROM 
    (
        SELECT city, event_time uv_time,1 AS uv FROM  tb_get_car_record
        UNION ALL
        SELECT city, end_time uv_time,-1 AS uv FROM  tb_get_car_record WHERE order_id IS NULL
        UNION ALL
        SELECT city, IFNULL(start_time,finish_time) uv_time,-1 AS uv FROM tb_get_car_order LEFT JOIN tb_get_car_record USING(order_id)
    ) t1
    WHERE DATE_FORMAT(uv_time,'%Y%m')='202110'
) t2
GROUP BY citY 
ORDER BY max_wait_uv, citY

done


参考牛客网盐咸咸的题解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值