【问题标题】:How to get first and last day of week in Oracle?如何在 Oracle 中获取一周的第一天和最后一天?
【发布时间】:2011-04-01 15:31:31
【问题描述】:

我需要从一些格式如下的字符串中获取一周的第一天和最后一天:

'201118'

其中 2011 是年份,18 是周数。知道周数,如何获得一周的第一天和最后一天?

我该怎么做?

【问题讨论】:

标签: sql oracle


【解决方案1】:

select TRUNC(sysdate, 'iw') AS iso_week_start_date,
       TRUNC(sysdate, 'iw') + 7 - 1/86400 AS iso_week_end_date
from dual;

select 
TRUNC (sysdate, 'mm') AS month_start_date,
LAST_DAY (TRUNC (sysdate, 'mm')) + 1 - 1/86400 AS month_end_date
from dual;

【讨论】:

  • 如果你想提取日期的其他元素,有 Oracle 文档很有用 - 目前在这里:docs.oracle.com/cd/B19306_01/server.102/b14200/… 或谷歌“oracle 中的圆形和截断日期函数”如果他们移动它跨度>
  • 为什么是1/86400?有这方面的文档吗?
【解决方案2】:

如果您使用的是 Oracle,此代码可以帮助您:

select 
TRUNC(sysdate, 'YEAR') Start_of_the_year,
TRUNC(sysdate, 'MONTH') Start_of_the_month,
TRUNC(sysdate, 'DAY') start_of_the_week,
TRUNC(sysdate+365, 'YEAR')-1 End_of_the_year,
TRUNC(sysdate+30, 'MONTH')-1 End_of_the_month,
TRUNC(sysdate+6, 'DAY')-1 end_of_the_week
from dual;


select 
TRUNC(sysdate, 'YEAR') Start_of_the_year,
TRUNC(sysdate+365, 'YEAR')-1 End_of_the_year,
TRUNC(sysdate, 'MONTH') Start_of_the_month,
TRUNC(sysdate+30, 'MONTH')-1 End_of_the_month,
TRUNC(sysdate, 'DAY')+1 start_of_the_week,  -- starting Monday
TRUNC(sysdate+6, 'DAY') end_of_the_week     -- finish Sunday
from dual;

【讨论】:

    【解决方案3】:
    SQL> var P_YEARWEEK varchar2(6)
    SQL> exec :P_YEARWEEK := '201118'
    
    PL/SQL procedure successfully completed.
    
    SQL> with t as
      2  ( select substr(:P_YEARWEEK,1,4) year
      3         , substr(:P_YEARWEEK,5,2) week
      4      from dual
      5  )
      6  select year
      7       , week
      8       , trunc(to_date(year,'yyyy'),'yyyy')                              january_1
      9       , trunc(trunc(to_date(year,'yyyy'),'yyyy'),'iw')                  monday_week_1
     10       , trunc(trunc(to_date(year,'yyyy'),'yyyy'),'iw') + (week - 1) * 7 start_of_the_week
     11       , trunc(trunc(to_date(year,'yyyy'),'yyyy'),'iw') + week  * 7 - 1  end_of_the_week
     12    from t
     13  /
    
    YEAR WE JANUARY_1           MONDAY_WEEK_1       START_OF_THE_WEEK   END_OF_THE_WEEK
    ---- -- ------------------- ------------------- ------------------- -------------------
    2011 18 01-01-2011 00:00:00 27-12-2010 00:00:00 25-04-2011 00:00:00 01-05-2011 00:00:00
    
    1 row selected.
    

    问候,
    抢。

    【讨论】:

      【解决方案4】:
      SELECT NEXT_DAY (TO_DATE ('01/01/'||SUBSTR('201118',1,4),'MM/DD/YYYY')+(TO_NUMBER(SUBSTR('201118',5,2))*7)-3,'SUNDAY')-7 first_day_wk,
          NEXT_DAY (TO_DATE ('01/01/'||SUBSTR('201118',1,4),'MM/DD/YYYY')+(TO_NUMBER(SUBSTR('201118',5,2))*7)-3,'SATURDAY') last_day_wk FROM dual
      

      【讨论】:

        【解决方案5】:

        假设您的意思是相对于一年中的第一天的几周......

        SELECT first_day_of_week, first_day_of_week+6 last_day_of_week
        FROM (
          SELECT TO_DATE(YEAR||'0101','YYYYMMDD') + 7 * (week-1) first_day_of_week
          FROM (
            SELECT substr(yearweek,1,4) YEAR, to_number(substr(yearweek,5)) week
            FROM (
              SELECT '201118' yearweek FROM dual
            )
          )
        )
        ;
        

        【讨论】:

        • 实际上,我需要一周的第一天是星期一,一周的最后一天是星期日。代码 201053 表示 2010 年的最后一周,它也可能包含 2011 年的第一天。例如,201053 是 29/12/2010 - 5/1/2011。像这样的......
        【解决方案6】:

        你可以试试这个方法:

        1. 获取当前日期。

        2. 加上等于当前日期年份与指定年份之差的年数。

        3. 减去最后获得日期的星期数的天数(它会得到某个星期的最后一天)。

        4. 添加周数,即最后获得日期的周数与指定周数之间的差,这将得出所需周的最后一天。

        5. 减去 6 天得到第一天。

        【讨论】:

          【解决方案7】:

          除非这是一次性的数据转换,否则您可能会从使用日历表中受益。

          有了这样的表格,在除了常规 ISO 周之外,过滤或汇总非标准期间的数据变得非常容易。周通常在公司和其中的部门之间表现得有些不同。一旦你离开“ISO-land”,内置的日期功能就帮不了你了。

          create table calender(
             day           date      not null -- Truncated date
            ,iso_year_week number(6) not null -- ISO Year week  (IYYYIW)
            ,retail_week   number(6) not null -- Monday to Sunday (YYYYWW)
            ,purchase_week number(6) not null -- Sunday to Saturday (YYYYWW)
            ,primary key(day)
          );
          

          您可以为“purchase_weeks”或“retail_weeks”创建额外的表格,或者只是动态汇总:

          select a.colA
                ,a.colB
                ,b.first_day
                ,b.last_day
            from your_table_with_weeks a
            join (select iso_year_week
                        ,min(day) as first_day
                        ,max(day) as last_day
                    from calendar
                   group  
                      by iso_year_week
                 ) b on(a.iso_year_week = b.iso_year_week)
          

          如果您处理大量记录,动态聚合不会产生显着差异,但如果您执行单行,您也会受益于为几周创建表。

          使用日历表提供了一个微妙的性能优势,因为优化器可以对静态列提供比嵌套add_months(to_date(to_char())) 函数调用更好的估计。

          【讨论】:

            【解决方案8】:

            另一个解决方案(星期一是第一天):

            select 
                to_char(sysdate - to_char(sysdate, 'd') + 2, 'yyyymmdd') first_day_of_week
                , to_char(sysdate - to_char(sysdate, 'd') + 8, 'yyyymmdd') last_day_of_week
            from
                dual
            

            【讨论】:

              【解决方案9】:

              另一种解决方案是

              SELECT 
                ROUND((TRUNC(SYSDATE) - TRUNC(SYSDATE, 'YEAR')) / 7,0) CANTWEEK,
                NEXT_DAY(SYSDATE, 'SUNDAY') - 7 FIRSTDAY,
                NEXT_DAY(SYSDATE, 'SUNDAY') - 1 LASTDAY
              FROM DUAL
              

              你必须将cantweek与年份连接起来

              【讨论】:

                【解决方案10】:

                @cem 的回答,有一个缺陷,如果sysdate 是星期天,它会返回下一个星期一。 受他的回答启发,这里有一个经过几周的测试:

                select 
                    (sysdate - to_char(sysdate-1, 'd') + 1) first_day_of_week --A monday here
                from dual
                

                【讨论】:

                  【解决方案11】:
                  SELECT TRUNC(SYSDATE,'D') "1ST_DAY", TRUNC(SYSDATE,'D') + 6 LAST_DAY FROM DUAL
                  

                  【讨论】:

                    【解决方案12】:

                    其实我是这样干的:

                        select case myconfigtable.valpar
                           when 'WEEK' then to_char(next_day(datetime-7,'Monday'),'DD/MM/YYYY')|| ' - '|| to_char(next_day(datetime,'Sunday'),'DD/MM/YYYY')
                           when 'MONTH' then to_char(to_date(yearweek,'yyyyMM'),'DD/MM/YYYY')  || ' - '|| to_char(last_day(to_date(yearweek,'yyyyMM')),'DD/MM/YYYY')
                           else 'NA'
                           end
                    from
                    (
                    select to_date(YEAR||'01','YYYYMM') + 7 * (WEEK - 1) datetime, yearweek
                           from
                           (
                           select substr(yearweek,1,4) YEAR,
                                  to_number(substr(yearweek,5)) WEEK,
                                  yearweek
                           from (select '201018' yearweek from dual
                                )
                           )
                    ), myconfigtable myconfigtable
                     where myconfigtable.codpar='TYPEOFPERIOD'
                    

                    【讨论】:

                      【解决方案13】:

                      我认为这只是一个简单的选择语句。我希望它有效,因为我无法在家里测试它,因为我这里没有 Oracle 数据库;-)

                      select to_date('201118', 'YYYYWW'), to_date('201118', 'YYYYWW')+7 from dual;
                      

                      您必须小心,因为 WW 和 IW 之间存在差异。这是一篇解释差异的文章:http://rwijk.blogspot.com/2008/01/date-format-element-ww.html

                      【讨论】:

                      • 不幸的是,“WW”和“IW”日期格式似乎仅用于输出。我也先尝试过。
                      【解决方案14】:

                      一周的第一天(星期一):

                      SELECT TO_DATE(to_char(sysdate,'YYYY')||'0101','YYYYMMDD') + 7 * to_number(to_char(sysdate,'WW')-1)-1 first_day_week FROM dual;
                      

                      一周的最后一天(星期日):

                      SELECT TO_DATE(to_char(sysdate,'YYYY')||'0101','YYYYMMDD') + 7 * to_number(to_char(sysdate,'WW')-1)+5 last_day_week FROM dual;
                      

                      在这些公式中替换您的日期或日期字段将对您有用!

                      【讨论】:

                        猜你喜欢
                        • 2021-07-21
                        • 2016-07-18
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多