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

注:参考文章:

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.mfbz.cn/a/389223.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JAVA-Day86】守护线程

守护线程 守护线程摘要引言1. 了解守护线程:它是什么?👻特点和用途示例代码 2. 为何我们需要守护线程?👻辅助性任务处理不阻止程序的正常运行重要的清理工作示例代码📚 3. 如何创建和管理守护线程&#xff…

QT 工具栏 状态栏 停靠部件 核心部件

添加/删除工具栏 删除工具栏方法和删除菜单栏方法一样,不过工具栏可以有多个,所以每次右键MainWindow对象,都可以看到添加工具栏的选项。 工具栏添加动作 新添加的QAction对象会在动作编辑器里找到(Action Editor)&a…

Java毕业设计-基于springboot的学院物资管理系统-第73期

获取源码资料,请移步从戎源码网:从戎源码网_专业的计算机毕业设计网站 项目介绍 基于springboot的学院物资管理系统:前端thymeleaf、jquery、layui,后端 maven、springmvc、spring、mybatis,有配套报告文档&#xff…

微信小程序的疑惑总结

未解决&#xff1a; 1.storebindings 这里的storebindings是什么 2.空行怎么写&#xff1f; 我用这个<text>\n</text>写&#xff0c;在模拟器上好使&#xff0c;在真机上显示\n 解决方法&#xff1a;在组件里写class类名&#xff0c;wxss里面改高度 已解决&am…

LD-802D-X6

LD-802D-X6足浴按摩器&#xff0c;买个给老人家&#xff0c;解决泡脚越泡越冷&#xff0c;调节温度和定式问题&#xff0c; 按摩功能老人体验说太痒&#xff0c;转太快了&#xff0c;哈哈 下面是安装步骤使用说明 其实这包零件就是安装底部4个轮子&#xff0c;4个轮子的中间滚…

【分享】图解ADS+JLINK调试ARM

文章是对LPC2148而写的&#xff0c;但是对三星的44B0芯片同样适用&#xff0c;只需要在选择时将相应的CPU选择的S3C44B0就可以了。 JLINK在ADS下调试心得 前两天一个客户用jlink在ADS下调试LPC2148总报错&#xff0c;这个错误我之前在调试LPC2200的时候也碰到过&#xff0c;后…

Nuxt3+Vue3(Composition API)+TS+Vite+Ant Design Vue 搭建

最近官网搭建选择了nuxtjs&#xff0c;由于框架更新了&#xff0c;其中语法也有很多变化&#xff0c;中间遇到了一些问题点做下总结。 nuxt3官方文档地址&#xff1a;https://nuxt.com/docs/getting-started/installation 安装 在安装Nuxt3之前&#xff0c;你需要保证你的nod…

【AIGC】Stable Diffusion的常见错误

Stable Diffusion 在使用过程中可能会遇到各种各样的错误。以下是一些常见的错误以及可能的解决方案&#xff1a; 模型加载错误&#xff1a;可能出现模型文件损坏或缺失的情况。解决方案包括重新下载模型文件&#xff0c;确保文件完整并放置在正确的位置。 依赖项错误&#x…

【C深度解剖】前置++与后置++

简介&#xff1a;本系列博客为C深度解剖系列内容&#xff0c;以某个点为中心进行相关详细拓展 适宜人群&#xff1a;已大体了解C语法同学 作者留言&#xff1a;本博客相关内容如需转载请注明出处&#xff0c;本人学疏才浅&#xff0c;难免存在些许错误&#xff0c;望留言指正 作…

飞天使-k8s知识点17-kubernetes实操2-pod探针的使用

文章目录 探针的使用容器探针启动实验1-启动探针的使用-startupprobeLiveness Probes 和 Readiness Probes演示若存在started.html 则进行 探针的使用 kubectl edit deploy -n kube-system corednslivenessprobe 的使用 livenessProbe:failureThreshold: 5httpGet:path: /heal…

ubuntu22.04@laptop OpenCV Get Started: 009_image_thresholding

ubuntu22.04laptop OpenCV Get Started: 009_image_thresholding 1. 源由2. image_thresholding应用Demo2.1 C应用Demo2.2 Python应用Demo 3. 重点分析3.1 Binary Thresholding ( THRESH_BINARY )3.2 Inverse-Binary Thresholding ( THRESH_BINARY_INV )3.3 Truncate Threshold…

嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第五天-ARM Linux编程之字符设备驱动(物联技术666)

链接&#xff1a;https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd1688 提取码&#xff1a;1688 教学内容&#xff1a; 1、内核模块的简单框架&#xff1a; __init __exit执行完后就释放空间 简单框架&#xff1a;包含三个部分 1&#xff09;模块初始化和模块退出函数…

leetcode刷题记录:暴力搜索算法01 - 回溯

参考&#xff1a;labuladong的算法小抄 https://labuladong.online/algo/essential-technique/backtrack-framework/ 这篇太牛了&#xff0c;一个模板把所有的排列组合子集问题全秒了。 1. 简介 暴力搜索算法&#xff1a;回溯、dfs、bfs。这些都可以看做是从二叉树算法衍生出来…

个人 AI 的革命:Nvidia‘s Chat with RTX 深度探索

个人 AI 的革命&#xff1a;Nvidias Chat with RTX 深度探索 Nvidia 推出的 Chat with RTX 预示着个人 AI 新时代的到来。2 月 13 日&#xff0c;Nvidia 官宣了自家的 AI 聊天机器人&#xff0c;这不仅是人工智能交互的渐进式改进&#xff1b;更代表了个人如何利用自己的数据进…

Dirty PageTable

前言 Dirty PageTable 是一种针对堆相关漏洞的利用手法&#xff0c;主要就是针对 PTE 进行攻击。 参考文章&#xff1a; Dirty Pagetable: A Novel Exploitation Technique To Rule Linux Kernel – 该利用方式提出原文 上述文章已经讲的非常清楚了&#xff0c;就是实操写 e…

25天物理探索旅程 - 第四天:光的奇妙旅程揭秘

第四天&#xff0c;我们的科普探险队将踏上一段非凡的旅程&#xff0c;目标是揭开光——这位宇宙间最具魔法特质的信使的秘密面纱。今天&#xff0c;我们将以一种轻松愉快、幽默风趣的方式探讨光的本质&#xff0c;像看一场生动有趣的魔术表演般&#xff0c;领略光那波粒二象性…

Java基础常见面试题总结-并发(一)

线程池 线程池&#xff1a;一个管理线程的池子。 为什么平时都是使用线程池创建线程&#xff0c;直接new一个线程不好吗&#xff1f; 嗯&#xff0c;手动创建线程有两个缺点 不受控风险频繁创建开销大 为什么不受控&#xff1f; 系统资源有限&#xff0c;每个人针对不同业…

垃圾分类|城市垃圾分类管理系统|基于Springboot的城市垃圾分类管理系统设计与实现(源码+数据库+文档)

城市垃圾分类管理系统目录 目录 基于Springboot的城市垃圾分类管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、垃圾列表 2、公告信息管理 3、公告类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 …

thinkphp+vue企业产品展示网站f7enu

本文首先介绍了企业产品展示网站管理技术的发展背景与发展现状&#xff0c;然后遵循软件常规开发流程&#xff0c;首先针对系统选取适用的语言和开发平台&#xff0c;根据需求分析制定模块并设计数据库结构&#xff0c;再根据系统总体功能模块的设计绘制系统的功能模块图&#…

qml之Control类型布局讲解,padding属性和Inset属性细讲

1、Control布局图 2、如何理解&#xff1f; *padding和*Inset参数如何理解呢&#xff1f; //main.qml import QtQuick 2.0 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import QtQuick.Controls 1.4 import QtQml 2.12ApplicationWindow {id: windowvisible: …
最新文章