HiveSQL——统计当前时间段的有客人在住的房间数量

news2024/11/27 7:26:22

注:参考文章:

HiveSQL一天一个小技巧:如何统计当前时间点状态情况【辅助变量+累计变换思路】_sql查询统计某状态出现的次数及累计时间-CSDN博客文章浏览阅读2k次,点赞6次,收藏8次。本文总结了一种当前时间点状态统计的思路和方法,对于此类问题主要采用构造辅助计数变量及累加变换思路进行求解。常见的场景有:直播同时在线人数、服务器实时并发数、公家车当前时间段人数、某个仓库的货物积压数量,某一段时间内的同时处于服务过程中的最大订单量等_sql查询统计某状态出现的次数及累计时间https://blog.csdn.net/godlovedaniel/article/details/129881211

0 需求描述

 

 1 数据准备

create table if not exists table23
(
    user_id     int comment '用户id',
    room_num    string comment '房间号',
    in_time     string comment '入住时间',
    out_time    string comment '离店时间'
)
    comment '旅客入住离店表';

insert overwrite table table23
values (7, '2004', '2021-03-05','2021-03-07'),
       (23,'2010', '2021-03-05','2021-03-06'),
       (7, '1003', '2021-03-07','2021-03-08'),
       (8, '2014', '2021-03-07','2021-03-08'),
       (14, '3001','2021-03-07','2021-03-10'),
       (18, '3002','2021-03-08','2021-03-10'),
       (23, '3020','2021-03-08','2021-03-09'),
       (25, '2006','2021-03-09','2021-03-12');

2 数据分析

   需求:求出每个时间段,有客人在住的房间数量。

   如果只考虑一人一房,可以借助于【直播间同时在线人数】统计的思路,相关sql逻辑指路:

HiveSQL题——聚合函数(sum/count/max/min/avg)-CSDN博客文章浏览阅读1.1k次,点赞19次,收藏19次。HiveSQL题——聚合函数(sum/count/max/min/avg)https://blog.csdn.net/SHWAITME/article/details/135918264?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170804307516800211583058%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=170804307516800211583058&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-135918264-null-null.nonecase&utm_term=%E7%9B%B4%E6%92%AD%E9%97%B4&spm=1018.2226.3001.4450  入住时间加辅助标记记为1,离店时间加辅助标记记为-1,并按照时间进行顺序排序,求当前累计值,具体SQL如下

select
    start_time,
    end_time,
    acc_cnt
from (select
          `time`                               as start_time,
          lead(`time`) over ( order by `time`) as end_time,
          acc_cnt
      from (select
                `time`,
                sum(flag) over (order by `time`) as acc_cnt
            from (
                     select
                         in_time as `time`,
                         1   as flag
                     from table23
                     union all
                     select
                         out_time as `time`,
                         -1   as flag
                     from table23
                 ) t1
           ) t2
      group by `time`, acc_cnt
     ) t
where end_time is not null;

   上述代码需要考虑一个问题:如果有多个人共住一房间,今天退了一个人,明天又退了一个人,后天的时候才退完,虽然这期间一直有人在退,但房间还是有人住的,这种情况是不是也算【有客人在住的房间】? 如果考虑上述情况,需要对累加的状态进行调整,此时需要考虑每个房间中截止当前时间的人数情况

第一步:先求出每个房间截至当前时间人数累计值,作为状态判断辅助条件

select
    `time`,
    room_num,
    sum( user_cnt) over (partition by room_num order by `time`) user_cnt
from (
         select
             in_time as  `time`,
             room_num,
             count(user_id) user_cnt
         from table23
         group by in_time, room_num
         union all
         select
             out_time as   `time`,
             room_num,
             -1 * count(user_id) user_cnt
         from table23
         group by out_time, room_num
     ) t1

第二步:基于累计的每个房间人数进行判断:如果房间有人就标记1,没有人时候就标记为-1。代码为:case when user_cnt > 0 时标记1,否则标记-1

select
    `time`,
     room_num,
     user_cnt,
    case when user_cnt > 0 then 1 else -1 end flag
from (select
         `time`,
          room_num,
          sum(user_cnt) over (partition by room_num order by `time`) user_cnt
      from (
               select
                   in_time as `time`,
                   room_num,
                   count(user_id) user_cnt
               from table23
               group by in_time, room_num
               union all
               select
                   out_time as `time`,
                   room_num,
                   -1 * count(user_id) user_cnt
               from table23
               group by out_time, room_num
           ) t1
     ) t2;

第三步:基于第二步的结果,计算截止当前时间点的有人入住的房间数量 acc_cnt,SQL如下:

select
    `time`,
    room_num,
    user_cnt,
    case when user_cnt > 0 then 1 else -1 end flag,
    sum(case when user_cnt > 0 then 1 else -1 end) over (order by `time`) acc_cnt
from (select
          `time`,
          room_num,
          sum(user_cnt) over (partition by room_num order by `time`) user_cnt
      from (
               select
                   in_time as `time`,
                   room_num,
                   count(user_id) user_cnt
               from table23
               group by in_time, room_num
               union all
               select
                   out_time as `time`,
                   room_num,
                   -1 * count(user_id) user_cnt
               from table23
               group by out_time, room_num
           ) t1
     ) t2;

 第四步:基于第三步的结果,对时间time 和截止当前时间点的有人入住的房间数量acc_cnt这两个字段进行去重,SQL如下:

select
    `time`,
    acc_cnt
from (
         select
             `time`,
             room_num,
             user_cnt,
             case when user_cnt > 0 then 1 else -1 end                             flag,
             sum(case when user_cnt > 0 then 1 else -1 end) over (order by `time`) acc_cnt
         from (select
                   `time`,
                   room_num,
                   sum(user_cnt) over (partition by room_num order by `time`) user_cnt
               from (
                        select
                            in_time as     `time`,
                            room_num,
                            count(user_id) user_cnt
                        from table23
                        group by in_time, room_num
                        union all
                        select
                            out_time as         `time`,
                            room_num,
                            -1 * count(user_id) user_cnt
                        from table23
                        group by out_time, room_num
                    ) t1
              ) t2
     ) t3
group by `time`, acc_cnt

 

  第五步:基于第四步的结果,通过lead函数(对time字段往后偏移一行)求出当前数据的结束时间end_time,SQL如下:

select
   `time` as start_time,
    lead(`time`, 1) over (order by `time`) as end_time,
    acc_cnt
from (
         select
             `time`,
             acc_cnt
         from (
                  select
                      `time`,
                      room_num,
                      user_cnt,
                      case when user_cnt > 0 then 1 else -1 end                             flag,
                      sum(case when user_cnt > 0 then 1 else -1 end) over (order by `time`) acc_cnt
                  from (select
                            `time`,
                            room_num,
                            sum(user_cnt) over (partition by room_num order by `time`) user_cnt
                        from (
                                 select
                                     in_time as     `time`,
                                     room_num,
                                     count(user_id) user_cnt
                                 from table23
                                 group by in_time, room_num
                                 union all
                                 select
                                     out_time as         `time`,
                                     room_num,
                                     -1 * count(user_id) user_cnt
                                 from table23
                                 group by out_time, room_num
                             ) t1
                       ) t2
              ) t3
         group by `time`, acc_cnt
     ) t4

   

  :基于第五步的结果,过滤掉end_time 是null的数据,SQL如下:

select
    start_time,
    end_time,
    acc_cnt
from (
         select
             `time`  as start_time,
             lead(`time`, 1) over (order by `time`) as end_time,
             acc_cnt
         from (
                  select
                      `time`,
                      acc_cnt
                  from (
                           select
                               `time`,
                               room_num,
                               user_cnt,
                               case when user_cnt > 0 then 1 else -1 end as  flag,
                               sum(case when user_cnt > 0 then 1 else -1 end) over (order by `time`) acc_cnt
                           from (select
                                     `time`,
                                     room_num,
                                     sum(user_cnt) over (partition by room_num order by `time`) user_cnt
                                 from (
                                          select
                                               in_time as `time`,
                                               room_num,
                                               count(user_id) user_cnt
                                          from table23
                                          group by in_time, room_num
                                          union all
                                          select
                                               out_time as `time`,
                                               room_num,
                                               -1 * count(user_id) user_cnt
                                          from table23
                                          group by out_time, room_num
                                      ) t1
                                ) t2
                       ) t3
                  group by `time`, acc_cnt
              ) t4
     ) t5
where end_time is not null;

3 小结

   针对【每个时间段的直播同时在线人数】 【每个时间段有客人在住的房间数量】这种类型的题目,本质是对(截至)当前时间点的状态统计。这种问题常见的解决思路是:对当前时间点的状态打标记flag,之后基于标记flag做开窗计算(结合窗口函数)或聚合计算

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1450901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue 进阶系列丨实现简易VueRouter

‍‍Vue 进阶系列教程将在本号持续发布,一起查漏补缺学个痛快!若您有遇到其它相关问题,非常欢迎在评论中留言讨论,达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧! 2013年7月28日,尤雨溪第一次在 G…

springboot集成elk实现日志采集可视化

一、安装ELK 安装ELK组件请参考我这篇博客:windows下安装ELK(踩坑记录)_windows上安装elk教程-CSDN博客 这里不再重复赘述。 二、编写logstash配置 ELK组件均安装好并成功启动,进入到logstash组件下的config文件夹,创建logstash.conf配置…

Three.JS教程5 threejs中的材质

Three.JS教程5 threejs中的材质 一、什么是Three.js材质?二、Three.js的材质类型1. 材质类型2. 材质的共用属性(1).alphaHash : Boolean(2).alphaTest : Float(3).alphaToCoverage : Boolean&am…

使用 Mermaid 创建流程图,序列图,甘特图

使用 Mermaid 创建流程图和图表 Mermaid 是一个流行的 JavaScript 库,用于创建流程图、序列图、甘特图和其他各种图表。它的简洁语法使得创建图表变得非常简单,无需复杂的绘图工具或专业的编程技能。在本文中,我们将讲解如何使用 Mermaid 来创…

卷积神经网络的基本结构

卷积神经网络的基本结构 与传统的全连接神经网络一样,卷积神经网络依然是一个层级网络,只不过层的功能和形式发生了变化。 典型的CNN结构包括: 数据输入层(Input Layer)卷积层(Convolutional Layer&#x…

Android 9.0 禁用adb shell input输入功能

1.前言 在9.0的系统rom产品开发中,在进行一些定制开发中,对于一些adb shell功能需要通过属性来控制禁止使用input 等输入功能,比如adb shell input keyevent 响应输入事件等,所以就需要 熟悉adb shell input的输入事件流程,然后来禁用adb shell input的输入事件功能,接…

函数求导法则【高数笔记】

【分类】 1. 四则运算求导 2. 复合运算求导 3. 整体思想求导 #整体思想求导本质是运用复合运算求导,只不过是对复合运算求导的一种精炼 #无论是具体函数还是抽象函数求导,方法是一致的 【四则运算求导】 加,减,乘,除&a…

openEuler 22.03 LTS 上源码安装 PostgreSQL 15

安装PostgreSQL 15 1 安装必要的依赖 #yum install -y readline-devel zlib-devel gcc2、下载源码 # wget https://ftp.postgresql.org/pub/source/v15.6/postgresql-15.6.tar.gz # tar -xzvf postgresql-15.6.tar.gz3 配置 # cd postgresql-15.6/ # ./configure4 编译安装…

JVM-JVM中对象的结构

对象内存布局 对象里的三个区: 对象头(Header):Java对象头占8byte。如果是数组则占12byte。因为JVM里数组size需要使用4byte存储。 标记字段MarkWord: 用于存储对象自身的运行时数据,它是synchronized实现轻…

图像识别基础之模板匹配

principle 图像匹配 本质:图像的相似度很高(矩阵的相似度很高) code /*\brief 我的图像匹配函数,获取差方和均值最小的矩阵作为结果\param srcPicFile:用以匹配的图像文件\param templatePicFile:模板图像文件\param destPicFile:输出的检测结果文件…

【读书笔记】ICS设备及应用攻击(一)

工控系统通常是由互联设备所构成的大型复杂系统,这些设备包括类似于人机界面(HMI)、PLC、传感器、执行器以及其他使用协商好的协议进行相互通信的设备。所有交互背后的驱动力都是软件,软件为工控系统中几乎所有部分的运行提供支撑…

鸿蒙开发-HarmonyOS UI架构

初步布局Index 当我们新建一个工程之后,首先会进入Index页。我们先简单的做一个文章列表的显示 class Article {title?: stringdesc?: stringlink?: string }Entry Component struct Index {State articles: Article[] []build() {Row() {Scroll() {Column() …

Python是垃圾?千万不要再学Python了?

“人生苦短,快学Python”这句话,相信大家都有看到过,但是有细心留意过,就会发现Python其实在网上的评价褒贬不一,有好评,也有差评。这就会给那些不懂Python却想要学Python的一些人造成困惑,我到…

主从延迟如何解决

最近项目上线,遇到了主从问题。按理说公司基建不至于出现这种问题,但就是出现了。可能因为用的不是原生的MySQL吧。主从延迟会给前端和服务端带来很多问题,需要花费时间用工程手段来解决,我认为这是很不合理的。 举几个因为主从延…

数字IC实践项目(9)— Tang Nano 20K: I2C OLED Driver

Tang Nano 20K: I2C OLED Driver 写在前面的话硬件模块RTL电路和相关资源报告SSD1306 OLED 驱动芯片SSD1306 I2C协议接口OLED 驱动模块RTL综合实现 总结 写在前面的话 之前在逛淘宝的时候偶然发现了Tang Nano 20K,十分感慨国产FPGA替代方案的进步之快;被…

51单片机项目(30)——基于51单片机的心率血氧脉搏检测的proteus仿真

1.功能设计 可以测量脉搏、心率、血氧浓度、体温,并且实时显示在LCD1602屏幕上,(第一行是体温血氧,第二行是心率脉搏)。 (需要完整源文件的,直接看最后一节) 另外,还…

PXE实现自动批量安装部署操作系统

目录 一、PXE介绍 二、PXE涉及的相关知识点 三、搭建PXE网络体系的前提 四、服务端要安装一系列的依赖环境 五、搭建 PXE 远程安装服务器 5.1、安装并启动TFTP服务 5.2、安装并启用 DHCP 服务 5.3、准备 Linux 内核、初始化镜像文件、准备 PXE 引导程序 5.4、安装FTP服…

【C++第二阶段】赋值运算符重载

你好你好&#xff01; 以下内容仅为当前认识&#xff0c;可能有不足之处&#xff0c;欢迎讨论&#xff01; 文章目录 赋值运算符重载 赋值运算符重载 实验①&#xff0c;还没有对析构运算符重载时 #include<iostream> #include<string> using namespace std;clas…

1Coze平台介绍

2023年随着OpenAI推出GPT 3.5&#xff0c;AI赛道变得更加火热。GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一种自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;用于生成文本、理解语言和进行各种语言任务。GPT是由OpenAI开发的&#xff0c;它…

【C语言】简单贪吃蛇实现保姆级教学!!!

关注小庄 顿顿解馋૮(˶ᵔ ᵕ ᵔ˶)ა 新年快乐呀小伙伴 引言&#xff1a; 小伙伴们应该都有一个做游戏的梦吧&#xff1f;今天让小庄来用C语言简单实现一下我们的童年邪典贪吃蛇&#xff0c;顺便巩固我们的C语言知识&#xff0c;请安心食用~ 文章目录 贪吃蛇效果一.游戏前工作…