博客 数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期-SQL开发实战(十九)

数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期-SQL开发实战(十九)

   数栈君   发表于 2023-03-03 11:47  237  0

前言
本篇文章讲解的主要内容是关于时间类型操作的进阶操作,这些操作在数仓中也属于比较难一些的时间操作案例了:如何一个SQL打印出当月日历或当年日历???如何统计一年内属于周内某一天的所有日期???如何确定某月内第一个和最后—个周内某天的日期???
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。

一、确定一年内属于周内某一天的所有日期
本例要求返回指定年份内的所有周五,用前面介绍的知识枚举全年信息,然后再过滤就可以。

SQL> with t as
2 (select trunc(sysdate, 'y') + (level - 1) as dy
3 from dual
4 connect by level <=
5 (add_months(trunc(sysdate, 'y'), 12) - trunc(sysdate, 'y')))
6 select dy, to_char(dy, 'day') as 周五 from t where to_char(dy, 'd') = 6;

DY 周五
----------- ---------------------------------------------------------------------------
2023-1-6 星期五
2023-1-13 星期五
2023-1-20 星期五
2023-1-27 星期五
2023-2-3 星期五
2023-2-10 星期五
2023-2-17 星期五
2023-2-24 星期五
2023-3-3 星期五
2023-3-10 星期五
2023-3-17 星期五
2023-3-24 星期五
2023-3-31 星期五
2023-4-7 星期五
2023-4-14 星期五
2023-4-21 星期五
2023-4-28 星期五
2023-5-5 星期五
2023-5-12 星期五
2023-5-19 星期五
2023-5-26 星期五
2023-6-2 星期五
2023-6-9 星期五
2023-6-16 星期五
2023-6-23 星期五
2023-6-30 星期五
2023-7-7 星期五
2023-7-14 星期五
2023-7-21 星期五
2023-7-28 星期五
2023-8-4 星期五
2023-8-11 星期五
2023-8-18 星期五
2023-8-25 星期五
2023-9-1 星期五
2023-9-8 星期五
2023-9-15 星期五
2023-9-22 星期五
2023-9-29 星期五
2023-10-6 星期五
2023-10-13 星期五
2023-10-20 星期五
2023-10-27 星期五
2023-11-3 星期五
2023-11-10 星期五
2023-11-17 星期五
2023-11-24 星期五
2023-12-1 星期五
2023-12-8 星期五
2023-12-15 星期五
2023-12-22 星期五
2023-12-29 星期五

52 rows selected


本例的要点是使用to_char(dy, 'd')来判断,这样可以避免不同客户端设置的影响,如:

SQL> select to_char(sysdate,'day')as day,to_char(sysdate,'d') as d from dual;

DAY D
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
星期三 4

SQL> alter session set nls_language=american;

Session altered


SQL> select to_char(sysdate,'day')as day,to_char(sysdate,'d') as d from dual;

DAY D
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
wednesday 4

SQL>


可以看到,当使用参数"day"时,不同字符集返回的结果不一样,但"d"不受影响。

二、确定某月内第一个和最后—个周内某天的日期
本例要求返回当月内第一个星期一与最后一个星期一,我们分别找上月末及当月末之前七天的下一周周一即可。

SQL> select next_day(trunc(sysdate,'mm')-1,2) as 第一周周一,
2 next_day(last_day(trunc(sysdate,'mm'))-7,2) as 最后一周的周一
3 from dual;

第一周周一 最后一周的周一
----------- -----------
2023-2-6 2023-2-27

三、创建本月日历
现在有个需求:要求你写一个sql打印出当月日历信息
看到这个需求你是不是有点懵逼?
怎么实现呢???
其实我们可以枚举指定月份所有的日期,并转换为对应的周信息,再按所在周做一次“行转列”即可,我这里会给大家展示一种行列互换的方式,因为未介绍pivot/unpivot,所以就用case when做。

SQL> with t as
2 (select trunc(sysdate, 'mm') + (level - 1) as dy
3 from dual
4 connect by level <=
5 (add_months(trunc(sysdate, 'mm'), 1) - trunc(sysdate, 'mm'))),
6 t1 as
7 (select to_char(dy, 'iw') as 所在周,
8 to_char(dy, 'dd') as 日期,
9 to_number(to_char(dy, 'd')) 周几
10 from t)
11 select max(case 周几
12 when 2 then
13 日期
14 end) 周一,
15 max(case 周几
16 when 3 then
17 日期
18 end) 周二,
19 max(case 周几
20 when 4 then
21 日期
22 end) 周三,
23 max(case 周几
24 when 5 then
25 日期
26 end) 周四,
27 max(case 周几
28 when 6 then
29 日期
30 end) 周五,
31 max(case 周几
32 when 7 then
33 日期
34 end) 周六,
35 max(case 周几
36 when 1 then
37 日期
38 end) 周天
39 from t1
40 group by 所在周
41 order by 所在周;

周一 周二 周三 周四 周五 周六 周天
--------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- ---------------------------------------------------------------------------
01 02 03 04 05
06 07 08 09 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28

SQL>


四、全年日历
前面介绍了一个月的日历怎么写。
如果是全年呢?方式大差不离!!!枚举365天就可以。
这里有一个小问题,第53周的数据to_char(日期,'iw')返回值有错,返回了第1周。

SQL> WITH x AS
2 (SELECT to_date('2013-12-27', 'yyyy-mm-dd') + (LEVEL - 1) AS d
3 FROM dual
4 CONNECT BY LEVEL <= 5)
5 SELECT d, to_char(d, 'day') AS DAY, to_char(d, 'iw') AS iw FROM x;

D DAY IW
----------- --------------------------------------------------------------------------- ---------------------------------------------------------------------------
2013-12-27 星期五 52
2013-12-28 星期六 52
2013-12-29 星期日 52
2013-12-30 星期一 01
2013-12-31 星期二 01

SQL>

这种数据需要用case when来处理。

SQL>
SQL> WITH x AS
2 (SELECT to_date('2013-12-27', 'yyyy-mm-dd') + (LEVEL - 1) AS d
3 FROM dual
4 CONNECT BY LEVEL <= 5),
5 x1 as
6 (SELECT d,
7 to_char(d, 'day') AS DAY,
8 to_char(d, 'mm') AS mm,
9 to_char(d, 'iw') AS iw
10 FROM x)
11 select d,
12 day,
13 mm,
14 iw,
15 case
16 when mm = 12 and iw = '01' then
17 '53'
18 else
19 iw
20 end as new_iw
21 from x1;

D DAY MM IW NEW_IW
----------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- --------------------------------------------------------------------------- ---------------------------------------------------------------------------
2013-12-27 星期五 12 52 52
2013-12-28 星期六 12 52 52
2013-12-29 星期日 12 52 52
2013-12-30 星期一 12 01 53
2013-12-31 星期二 12 01 53

SQL>


于是全年日历可查询为:

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/011bec62053e978f1090458ef5494d8c..png

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/2a1ce93777efddf4b4224238190c4b2b..png

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/afd6208b7d048302a693f1d431a3090c..png

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/08e32a715f7e40f020e91147d03ac26d..png

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/a8551f57348e5b586499ab6ee8cec8c8..png

————————————————
版权声明:本文为CSDN博主「赵延东的一亩三分地」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_28356739/article/details/129052200

0条评论
社区公告
  • 大数据领域最专业的产品&技术交流社区,专注于探讨与分享大数据领域有趣又火热的信息,专业又专注的数据人园地

最新活动更多
微信扫码获取数字化转型资料
钉钉扫码加入技术交流群