SQL取日期为当前月份的第几周思路
Posted 大树的困惑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL取日期为当前月份的第几周思路相关的知识,希望对你有一定的参考价值。
问题背景
获取每个月的第几周包含跨年问题
当前有一份从20010101到20201231的数据,现在需要获得每个日期对应在每个月中的第几周,为了实现日历展示的那种格式
展示对应日期所在的是该月份的第几周。
**多种日期格式:**to_char(date,‘XXXX’)
YYYY:四位表示的年份
YYY,YY,Y:年份的最后三位、两位或一位,缺省为当前世纪
IYYY:ISO标准的四位年份
MM:01~12的月份编号
MON:缩写字符集表示
MONTH:全拼字符集表示的月份,右边用空格填补
Q:季度
W:当月第几周
WW:当年第几周
IW:ISO标准的年中的第几周
D:当周第几天
DD:当月第几天
DDD:当年第几天
DY:缩写字符集表示
DAY:全拼字符集表示的天 如(星期六)
HH,HH12:一天中的第几个小时,12进制表示法
HH24:一天中的第几个小时,取值为00~23
MI:一小时中的分钟
SS:一分钟中的秒
解决方案
第一种方法
用每年的第一天作为基数,
1.取出指定日期属于当年的第几周—num_week1
2.取出指定日期所在月的第一天,属于当年的第几周—num_week2
3.num_week1-num_week2 +1 可以算出当前日期属于当月的第几周
--num_week1 :to_char(to_date(Simple_date,'yyyymmdd'),'iw')
--num_week2 :to_char(TRUNC( to_date(Simple_date,'yyyymmdd'),'MM'),'iw')
SELECT simple_date,
to_char(to_date(Simple_date,'yyyymmdd'),'iw') - to_char(TRUNC( to_date(Simple_date,'yyyymmdd'),'MM'),'iw')+1 as week
FROM t_cal_date
按照这个逻辑直接取数会有问题,就是跨年的问题,当遇到跨年的时候,iw这种函数的方法会默认将不满一周的剩余几天规划到下一年,所以会出现部分异常数据
SELECT simple_date,
DENSE_RANK() over(partition by V_YEAR,V_MONTH order by rn2 ) V_M_WEEK
FROM (
SELECT simple_date,v_month,v_year,week,
max(simple_date) over(partition by V_YEAR,v_year_week,week ) as rn2
FROM (
SELECT simple_date,
to_char(to_date(simple_date,'yyyymmdd'),'mm') v_month ,
to_char(to_date(simple_date,'yyyymmdd'),'yyyy') v_year ,
to_char(to_date(simple_date,'yyyymmdd'),'iw') v_year_week ,
case when to_char(to_date(simple_date,'yyyymmdd'),'iw') < to_char(TRUNC( to_date(simple_date,'yyyymmdd'),'MM'),'iw')
then to_char(to_date(simple_date,'yyyymmdd'),'iw') + 1
else
to_char(to_date(simple_date,'yyyymmdd'),'iw') - to_char(TRUNC( to_date(simple_date,'yyyymmdd'),'MM'),'iw')+1
end as week
FROM t_cal_date
) a
)b
可以看到跨年的日期已经正常了
主要的修改逻辑是,进行二次排序
方法二:
也是用做差的方法计算出当前日期与参照日的周数,和当前月的第一天的周数相减,取得周数
1.选定参照日(20010101-星期一)
2.计算每个月的一号到参照日相差的天数,比计算出相差的周数(diff/7)
3.计算每个日期距离参照日相差的天数,以及相差的周数。
关联做差,便可以求出日期处于当前月的第几周
SELECT date_A.*,date_B.*,(date_A.Diff_Week-date_B.Diff_Week)+1 as WEEK_MONTH FROM
(
SELECT to_number(to_date(tar_date,'yyyymmdd')-to_date(begin_date,'yyyymmdd')) as diff_day,
ceil(to_number(to_date(tar_date,'yyyymmdd')-to_date(begin_date,'yyyymmdd')+1)/7) as diff_week,
substr(tar_date,1,6) as cur_yearmonth,
tar_date FROM
(
SELECT Simple_date as tar_date,20010101 as begin_date FROM t_cal_date
) ) date_A
left join
(
SELECT to_number(to_date(tar_date,'yyyymmdd')-to_date(begin_date,'yyyymmdd')) as diff_day,
ceil(to_number(to_date(tar_date,'yyyymmdd')-to_date(begin_date,'yyyymmdd')+1)/7) as diff_week,
substr(tar_date,1,6) as cur_yearmonth,
tar_date FROM
(
SELECT distinct TO_CHAR(TRUNC(to_date(Simple_date,'yyyymmdd'),'MONTH'),'yyyymmdd') as tar_date,20010101 as begin_date FROM t_cal_date
)
) date_B
on date_A.Cur_Yearmonth=date_B.Cur_Yearmonth
这种方式不存在跨年的问题
以上是关于SQL取日期为当前月份的第几周思路的主要内容,如果未能解决你的问题,请参考以下文章