当前位置: 首页 > news >正文

SQL面试题之区间合并问题

目录

0 需求

1 数据准备

2 数据分析

 2 小结


0 需求

给定多个时间段,每个时间段分为开始时间、结束时间,将相互重叠的多个时间段合并为一个区间

--数据:id、开始时间、结束时间
1 12 15
2 57 58
3 29 32
4 30 31
5 17 19
6 44 44
7 56 57
8 16 18

合并后结果如下;

--结果
flag	start_time	end_time
1	     12	        15
2	     16	        19
3	     29	        32
4	     44	        44
5	     56	        58

1 数据准备

create table test02 as
select 1 as id, 12 as start_time, 15 as end_time
union all
select 2 as id, 57 as start_time, 58 as end_time
union all
select 3 as id, 29 as start_time, 32 as end_time
union all
select 4 as id, 30 as start_time, 31 as end_time
union all
select 5 as id, 17 as start_time, 19 as end_time
union all
select 6 as id, 44 as start_time, 44 as end_time
union all
select 7 as id, 56 as start_time, 57 as end_time
union all
select 8 as id, 16 as start_time, 18 as end_time

2 数据分析

解题要点:如何判断哪些区间是要合并的?

其实换个角度就是哪些区间是交叉的,哪些是重复的?

判断思路:如果将起始时间,和结束时间进行排序,当前行的起始时间小于等于上一行的结束时间,那么日期就存在交叉,存在重复的数据。根据该条件我们可以设置断点,然后用经典的思路sum() over()来获取分组id,问题便得到解决。

第一步:按照起始时间和结束时间进行降序排序,获取上一行的结束时间,目的是为了比较

select id,
                            start_time,
                            end_time,
                            lag(end_time, 1, end_time) over (order by start_time asc, end_time asc) as lga_end_time
                     from test02

 

第二步:根据lag_end_time进行判断,当当前行的start_time <=  lag_end_time时候设置标记值0,否则为1(经典的按条件变化后的分组思路,这里一定是满足条件的时候置为0,不满足条件的时候置为1)

select id
                    , start_time
                    , end_time
                    , case when start_time <= lga_end_time then 0 else 1 end as flg --条件成立的时候为0,不成立的时候为1
               from (select id,
                            start_time,
                            end_time,
                            lag(end_time, 1, end_time) over (order by start_time asc, end_time asc) as lga_end_time
                     from test02

 第三步:按照sum() over()的方法获取分组id

 select id
              , start_time
              , end_time
              , sum(flg) over (order by start_time, end_time ) as grp_id
         from (select id
                    , start_time
                    , end_time
                    , case when start_time <= lga_end_time then 0 else 1 end as flg --条件成立的时候为0,不成立的时候为1
               from (select id,
                            start_time,
                            end_time,
                            lag(end_time, 1, end_time) over (order by start_time asc, end_time asc) as lga_end_time
                     from test02
                    ) t
              ) t

 第四步:在分组里获取,最小值及最大值,最小值即为起始点,最大值即为结束点,分组id即为id

最终的SQL如下:

select grp_id + 1      as id
     , min(start_time) as start_time
     , max(end_time)   as end_time
from (
         select id
              , start_time
              , end_time
              , sum(flg) over (order by start_time, end_time ) as grp_id
         from (select id
                    , start_time
                    , end_time
                    , case when start_time <= lga_end_time then 0 else 1 end as flg --条件成立的时候为0,不成立的时候为1
               from (select id,
                            start_time,
                            end_time,
                            lag(end_time, 1, end_time) over (order by start_time asc, end_time asc) as lga_end_time
                     from test02
                    ) t
              ) t
     ) t
group by grp_id

 2 小结

   本题为区间合并问题,问题比较经典,判断的核心思路是构造条件:

当前行的起始时间<=上一行的结束时间(按照起始时间和结束时间降序排序)。

然后利用经典的分组思路,在一个分组中求最小、最大值即为所求。

相关文章:

  • Linux用户和权限之一
  • 回溯法就是学不会2 —— 括号生成问题
  • ESP32 ESP-IDF TFT-LCD(ST7735 128x160) LVGL演示
  • 信息论学习笔记(二):离散无噪声系统
  • CentOS7启动SSH服务报错
  • 大咖说*计算讲谈社|商用车智能驾驶商业化实践
  • python笔记Ⅶ--函数返回值、作用域与命名空间、递归
  • 03 RocketMQ - Broker 源码分析
  • Java日志系列——规范化日志
  • 00前言说明-Qt自定义控件大全
  • 简历内容整理
  • 金仓数据库KingbaseES客户端编程接口指南-ado.net(7. Kdbnpg支持的类型和类型映射)
  • CTCLoss原理解读
  • 数字孪生|数字孪生装备-概念与内涵
  • 图像相似度对比分析软件,图像相似度算法有哪些
  • 深入了解以太坊
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • CAP 一致性协议及应用解析
  • CSS 专业技巧
  • gulp 教程
  • input实现文字超出省略号功能
  • Java 23种设计模式 之单例模式 7种实现方式
  • Java应用性能调优
  • unity如何实现一个固定宽度的orthagraphic相机
  • WebSocket使用
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 关于Flux,Vuex,Redux的思考
  • 机器学习 vs. 深度学习
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 码农张的Bug人生 - 初来乍到
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 删除表内多余的重复数据
  • 深入 Nginx 之配置篇
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • #ubuntu# #git# repository git config --global --add safe.directory
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (1)虚拟机的安装与使用,linux系统安装
  • (2)(2.10) LTM telemetry
  • (4)(4.6) Triducer
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (solr系列:一)使用tomcat部署solr服务
  • (zt)最盛行的警世狂言(爆笑)
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET Core 中的路径问题
  • .NET delegate 委托 、 Event 事件,接口回调
  • .net Stream篇(六)
  • .net 生成二级域名