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取日期为当前月份的第几周思路的主要内容,如果未能解决你的问题,请参考以下文章

Sql server判断某一日期是在第几季度

Sql server判断某一日期是在第几季度?

如何计算当前日期是当年的第几周

js根据当前时间获取当前季度,月份,和第几周

在mysql中得到当前日期是当月第几周

js实现获取当前时间是本月第几周和年的第几周的方法