【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
系列文章目录
【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事
【SQL开发实战技巧】系列(二):简单单表查询
【SQL开发实战技巧】系列(三):SQL排序的那些事
【SQL开发实战技巧】系列(四):从执行计划讨论UNION ALL与空字符串&UNION与OR的使用注意事项
【SQL开发实战技巧】系列(五):从执行计划看IN、EXISTS 和 INNER JOIN效率,我们要分场景不要死记网上结论
【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放
【SQL开发实战技巧】系列(七):从有重复数据前提下如何比较出两个表中的差异数据及对应条数聊起
【SQL开发实战技巧】系列(八):聊聊如何插入数据时比约束更灵活的限制数据插入以及怎么一个insert语句同时插入多张表
【SQL开发实战技巧】系列(九):一个update误把其他列数据更新成空了?Merge改写update!给你五种删除重复数据的写法!
【SQL开发实战技巧】系列(十):从拆分字符串、替换字符串以及统计字符串出现次数说起
【SQL开发实战技巧】系列(十一):拿几个案例讲讲translate|regexp_replace|listagg|wmsys.wm_concat|substr|regexp_substr常用函数
【SQL开发实战技巧】系列(十二):三问(如何对字符串字母去重后按字母顺序排列字符串?如何识别哪些字符串中包含数字?如何将分隔数据转换为多值IN列表?)
【SQL开发实战技巧】系列(十三):讨论一下常用聚集函数&通过执行计划看sum()over()对员工工资进行累加
【SQL开发实战技巧】系列(十四):计算消费后的余额&计算银行流水累计和&计算各部门工资排名前三位的员工
【SQL开发实战技巧】系列(十五):查找最值所在行数据信息及快速计算总和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report
【SQL开发实战技巧】系列(十六):数据仓库中时间类型操作(初级)日、月、年、时、分、秒之差及时间间隔计算
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
【SQL开发实战技巧】系列(十八):数据仓库中时间类型操作(进阶)INTERVAL、EXTRACT以及如何确定一年是否为闰年及周的计算
【SQL开发实战技巧】系列(十九):数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期?
【SQL开发实战技巧】系列(二十):数据仓库中时间类型操作(进阶)获取季度开始结束时间以及如何统计非连续性时间的数据
【SQL开发实战技巧】系列(二十一):数据仓库中时间类型操作(进阶)识别重叠的日期范围,按指定10分钟时间间隔汇总数据
【SQL开发实战技巧】系列(二十二):数仓报表场景☞ 从分析函数效率一定快吗聊一聊结果集分页和隔行抽样实现方式
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
【SQL开发实战技巧】系列(二十四):数仓报表场景☞通过案例执行计划详解”行转列”,”列转行”是如何实现的
【SQL开发实战技巧】系列(二十五):数仓报表场景☞结果集中的重复数据只显示一次以及计算部门薪资差异高效的写法以及如何对数据进行快速分组
【SQL开发实战技巧】系列(二十六):数仓报表场景☞聊聊ROLLUP、UNION ALL是如何分别做分组合计的以及如何识别哪些行是做汇总的结果行
文章目录
- 系列文章目录
- 前言
- 一、确定两个日期之间的工作天数
- 二、计算—年中周内各日期的次数
- 三、确定当前记录和下一条记录之间相差的天数
- 总结
前言
本篇文章讲解的主要内容是:如何确定两个日期之间的工作日有多少天、计算—年中每周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。
一、确定两个日期之间的工作天数
现在有个需求:返回员工BLAKE与JONES聘用日期之间的工作天数。
先看一下初始数据:
SQL> select ename,hiredate from emp where ename in ('BLAKE','JONES');ENAME HIREDATE
---------- -----------
BLAKE 1981-5-1
JONES 1981-4-2
接下来一步步分析这个需求怎么做!
第一步,先初始化个600条数据的临时表T,具体啥用待会给大家说
with t as (
select level as id from dual connect by level<=600
)
第二步,通过max,min
与group by
将上面初始数据转为一行,这个结果做第二个临时表T1:
SQL> with t as2 (select level as id from dual connect by level <= 600),3 t1 as4 (select min(hiredate) as min_hd, max(hiredate) as max_hd5 from emp6 where ename in ('BLAKE', 'JONES'))7 select * from t1;MIN_HD MAX_HD
----------- -----------
1981-4-2 1981-5-1
第三步,枚举出来两个日期之间的间隔天数,不过日期相减需要+1,比如1~2天是2天,所以计算公式应该是(2-1)+1
。
SQL> with t as2 (select level as id from dual connect by level <= 600),3 t1 as4 (select min(hiredate) as min_hd, max(hiredate) as max_hd5 from emp6 where ename in ('BLAKE', 'JONES'))7 select (max_hd-min_hd)+1 as 天数 from t1;天数
----------30
第四步,将T表与T1表做个笛卡尔积,枚举出来这30天的所有日期。
SQL> set pagesize 200;
SQL>
SQL> with t as2 (select level as id from dual connect by level <= 600),3 t1 as4 (select min(hiredate) as min_hd, max(hiredate) as max_hd5 from emp6 where ename in ('BLAKE', 'JONES'))7 select min_hd + (t.id - 1) as 日期8 from t, t19 where t.id <= ((max_hd - min_hd) + 1);日期
-----------
1981-4-2
1981-4-3
1981-4-4
1981-4-5
1981-4-6
1981-4-7
1981-4-8
1981-4-9
1981-4-10
1981-4-11
1981-4-12
1981-4-13
1981-4-14
1981-4-15
1981-4-16
1981-4-17
1981-4-18
1981-4-19
1981-4-20
1981-4-21
1981-4-22
1981-4-23
1981-4-24
1981-4-25
1981-4-26
1981-4-27
1981-4-28
1981-4-29
1981-4-30
1981-5-130 rows selected
第五步,根据这些日期得到对应的工作日信息
SQL>
SQL> with t as2 (select level as id from dual connect by level <= 600),3 t1 as4 (select min(hiredate) as min_hd, max(hiredate) as max_hd5 from emp6 where ename in ('BLAKE', 'JONES')),7 t2 as8 (select min_hd + (t.id - 1) as 日期9 from t, t110 where t.id <= ((max_hd - min_hd) + 1))11 select 日期, to_char(日期, 'DY', 'NLS_DATE_LANGUAGE=American') as dy12 from t2;日期 DY
----------- ---------------------------------------------------------------------------
1981-4-2 THU
1981-4-3 FRI
1981-4-4 SAT
1981-4-5 SUN
1981-4-6 MON
1981-4-7 TUE
1981-4-8 WED
1981-4-9 THU
1981-4-10 FRI
1981-4-11 SAT
1981-4-12 SUN
1981-4-13 MON
1981-4-14 TUE
1981-4-15 WED
1981-4-16 THU
1981-4-17 FRI
1981-4-18 SAT
1981-4-19 SUN
1981-4-20 MON
1981-4-21 TUE
1981-4-22 WED
1981-4-23 THU
1981-4-24 FRI
1981-4-25 SAT
1981-4-26 SUN
1981-4-27 MON
1981-4-28 TUE
1981-4-29 WED
1981-4-30 THU
1981-5-1 FRI30 rows selected
第六步,过滤,把得到的结果汇总就是工作天数。
SQL> with t as2 (select level as id from dual connect by level <= 600),3 t1 as4 (select min(hiredate) as min_hd, max(hiredate) as max_hd5 from emp6 where ename in ('BLAKE', 'JONES')),7 t2 as8 (select min_hd + (t.id - 1) as 日期9 from t, t110 where t.id <= ((max_hd - min_hd) + 1)),11 t3 as12 (select 日期, to_char(日期, 'DY', 'NLS_DATE_LANGUAGE=American') as dy13 from t2)14 select count(*) from t3 where dy not in ('SAT', 'SUN');COUNT(*)
----------22
二、计算—年中周内各日期的次数
比如,计算一年内有多少天是星期一,多少天是星期二等,这个问题需要以下几步。
- 取得当前年度信息。
- 计算一年有多少天。
- 生成日期列表。
- 转换为对应的星期标识。
- 汇总。
那么接下来看怎么做!
SQL> with t as2 (select to_date('2023-01-01', 'yyyy-mm-dd') as 年初 from dual),3 t1 as4 (select 年初, add_months(年初, 12) as 下年初 from t),5 t2 as6 (select 年初, 下年初, 下年初 - 年初 as 天数 from t1),7 t3 as/*生成列表*/8 (select 年初 + (level - 1) as 日期 from t2 connect by level <= 天数),9 t4 as/*对数据进行转换*/10 (select 日期, to_char(日期, 'DY') as 星期 from t3)11 select 星期, count(*) as 天数 from t4 group by 星期;星期 天数
--------------------------------------------------------------------------- ----------
星期二 52
星期六 52
星期日 53
星期三 52
星期四 52
星期五 52
星期一 527 rows selected
三、确定当前记录和下一条记录之间相差的天数
首先需要把下一条记录的雇佣日期作为当前行,这需要用到lead()over()分析函数。
SQL> select deptno,2 ename,3 hiredate,4 lead(hiredate) over(order by hiredate) next_hd5 from emp6 where deptno = 10;DEPTNO ENAME HIREDATE NEXT_HD
------ ---------- ----------- -----------10 CLARK 1981-6-9 1981-11-1710 KING 1981-11-17 1982-1-2310 MILLER 1982-1-23
当数据提取到同一行后,再计算就比较简单:
SQL> with t as (2 select deptno,3 ename,4 hiredate,5 lead(hiredate) over(order by hiredate) next_hd6 from emp7 where deptno = 10)8 select ename,hiredate,next_hd-hiredate diff9 from t;ENAME HIREDATE DIFF
---------- ----------- ----------
CLARK 1981-6-9 161
KING 1981-11-17 67
MILLER 1982-1-23
和lead对应的就是lag函数,如果读者能记住两个函数的区别当然比较好,如果记不住,可直接实验。
SQL>
SQL> with t as (2 select deptno,3 ename,4 hiredate,5 lag(hiredate) over(order by hiredate) lag_hd,6 lead(hiredate) over(order by hiredate) lead_hd7 from emp8 where deptno = 10)9 select * from t;DEPTNO ENAME HIREDATE LAG_HD LEAD_HD
------ ---------- ----------- ----------- -----------10 CLARK 1981-6-9 1981-11-1710 KING 1981-11-17 1981-6-9 1982-1-2310 MILLER 1982-1-23 1981-11-17
总结
本章节的三个需求:确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
有些许难度,不过建议还是学会比较好。
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数相关推荐
- 【SQL开发实战技巧】系列(十八):数据仓库中时间类型操作(进阶)INTERVAL、EXTRACT以及如何确定一年是否为闰年及周的计算
系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...
- 【SQL开发实战技巧】系列(十六):数据仓库中时间类型操作(初级)日、月、年、时、分、秒之差及时间间隔计算
系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...
- 【SQL开发实战技巧】系列(十九):数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期?
系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...
- 【SQL开发实战技巧】系列(二十一):数据仓库中时间类型操作(进阶)识别重叠的日期范围,按指定10分钟时间间隔汇总数据
系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...
- 【SQL开发实战技巧】系列(七):从有重复数据前提下如何比较出两个表中的差异数据及对应条数聊起
系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...
- 【SQL开发实战技巧】系列(十二):三问(如何对字符串字母去重后按字母顺序排列字符串?如何识别哪些字符串中包含数字?如何将分隔数据转换为多值IN列表?)
系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...
- 【SQL开发实战技巧】系列(四十七):Oracle12C常用新特性☞非分区表在线转分区表online clause(不停业务+索引有效)
系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...
- 【SQL开发实战技巧】系列(三十七):数仓报表场景☞从表内始终只有近两年的数据,要求用两列分别显示其中一年的数据聊行转列隐含信息的重要性
系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...
- 【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放
系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...
最新文章
- android中仿qq最新版抽屉,Android实现3种侧滑效果(仿qq侧滑、抽屉侧滑、普通侧滑)...
- linux查看注册表信息,linux下登录档及其查看方法
- alt和title的区别与用法
- 中小型公司***的配置及NAT应用案例
- CAsyncSocket使用总结
- python实现oss文件下载
- 微软职位内部推荐-Software Engineer II-Senior Software Engineer for Satori
- 拉格朗日插值多项式及其余项
- 简述使jdbc连接mysql数据库_java中简述使用JDBC完成数据库操作的基本步骤。
- 符号回归工具之 geppy: Python中的基因表达编程框架
- Python基础 Zero to Hero面向对象编程(一)
- flea-common使用之本地国际化实现
- Camtasia Studio 录制视频保存为camrec格式后快速导出为AVI格式
- otc焊接机器人编程模拟软件_otc焊接机器人编程
- 2021数字四川创新大赛盛夏再起航
- 取消远程计算机控制,怎么脱离远程计算机控制?
- Price action价格行为交易法
- G1 GC详解及设置
- 基于深度学习的农作物病虫害识别
- 阿里云小程序时代来临,中小企业和商家该如何入局
热门文章
- 基于Java的在线网盘程序—ZFile(推荐开源项目)
- 深度学习常用非线性函数及其导数
- paddle-OCRv2预测部署
- DOS命令使用大全——浪子回头再来看
- 爬虫入门概念与硬核实战巩固(一)
- EhCache常用的memoryStoreEvictionPolicy(缓存算法)
- Cannot find table rule and default data source with logic tables: '[]'
- 【老生谈算法】matlab实现线性平滑滤波算法——线性平滑滤波算法
- 4.Spring Cloud (Hoxton.SR8) 实战笔记—项目中细节实现 约束 注意事项、模块难点总结、Lambda表达式
- 随想杂谈--一个GPIO控制两个按键的方法