简体   繁体   English

如何在 Oracle 中获取一周的第一天和最后一天?

[英]How to get first and last day of week in Oracle?

I need to get the first day and the last day of the week from some strings that have the format like this:我需要从一些格式如下的字符串中获取一周的第一天和最后一天:

'201118' '201118'

where 2011 is the year and 18 is the number of the week.其中 2011 是年份,18 是星期几。 Knowing the number of the week, how do I get the first and the last day of the week?知道星期几,我如何获得一周的第一天和最后一天?

How do I do this?我该怎么做呢?

WEEK星期

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

MONTH

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

If you are using Oracle, this code can help you:如果您使用的是 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;
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
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.

Regards,问候,
Rob.抢。

Assuming you mean weeks relative to the first day of the year ...假设您的意思是相对于一年中的第一天的几周......

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
    )
  )
)
;

Yet another solution (Monday is the first day):另一个解决方案(星期一是第一天):

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

Another solution is另一个解决方案是

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

You must concat the cantweek with the year您必须将 cantweek 与年份连接起来

Unless this is a one-off data conversion, chances are you will benefit from using a calendar table.除非这是一次性的数据转换,否则您很有可能会从使用日历表中受益。

Having such a table makes it really easy to filter or aggregate data for non-standard periods in addition to regular ISO weeks.除了常规的 ISO 周之外,拥有这样的表格可以非常轻松地过滤或汇总非标准时期的数据。 Weeks usually behave a bit differently across companies and the departments within them.周通常在公司及其内部部门之间的表现略有不同。 As soon as you leave "ISO-land" the built-in date functions can't help you.一旦你离开“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)
);

You can either create additional tables for "purchase_weeks" or "retail_weeks", or simply aggregate on the fly:您可以为“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)

If you process a large number of records, aggregating on the fly won't make a noticable difference, but if you are performing single-row you would benefit from creating tables for the weeks as well.如果您处理大量记录,动态聚合不会产生显着差异,但如果您执行单行,您也将从创建数周的表中受益。

Using calendar tables provides a subtle performance benefit in that the optimizer can provide better estimates on static columns than on nested add_months(to_date(to_char())) function calls.使用日历表提供了微妙的性能优势,因为优化器可以对静态列提供比嵌套add_months(to_date(to_char()))函数调用更好的估计。

You could try this approach:你可以试试这个方法:

  1. Get the current date.获取当前日期。

  2. Add the the number of years which is equal to the difference between the current date's year and the specified year.添加等于当前日期年份与指定年份之间的差的年数。

  3. Subtract the number of days that is the last obtained date's week day's number (and it will give us the last day of some week).减去最后获得日期的星期数的天数(它会给我们某个星期的最后一天)。

  4. Add the number of weeks which is the difference between the last obtained date's week number and the specified week number, and that will yield the last day of the desired week.添加上次获取日期的周数与指定周数之间的差的周数,这将产生所需周的最后一天。

  5. Subtract 6 days to obtain the first day.减去6天得到第一天。

Actually, I did something like this:实际上,我做了这样的事情:

    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'

@cem's answer, has a flaw, if sysdate is a sunday, it returns the monday following. @cem 的回答有一个缺陷,如果sysdate是星期日,它会返回接下来的星期一。 Inspired by his answer, here is one tested against few weeks:受到他的回答的启发,以下是一项针对几周的测试:

select 
    (sysdate - to_char(sysdate-1, 'd') + 1) first_day_of_week --A monday here
from dual
SELECT TRUNC(SYSDATE,'D') "1ST_DAY", TRUNC(SYSDATE,'D') + 6 LAST_DAY FROM DUAL
  • List item项目清单

Truc(sysdate, 'DAY') starts from monday Truc(sysdate, 'DAY')从星期一开始

  • List item项目清单

Truc(sysdate, 'DAY')+1 starts from tuesday Truc(sysdate, 'DAY')+1从星期二开始

First day of week (Monday):一周的第一天(星期一):

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

Last day of week (Sunday):一周的最后一天(星期日):

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

Substituting your date or date field in these formulas will work for you!在这些公式中替换您的日期或日期字段对您有用!

I think this is just a simple select statement.我认为这只是一个简单的选择语句。 I hope it works, because I couldn't test it at home, because I don't have a Oracle database here ;-)我希望它有效,因为我无法在家测试它,因为我这里没有 Oracle 数据库;-)

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

You have to be carefully because there is a difference between WW and IW.你必须小心,因为WW和IW之间存在差异。 Here is an article which explains the difference: http://rwijk.blogspot.com/2008/01/date-format-element-ww.html这是一篇解释差异的文章: http : //rwijk.blogspot.com/2008/01/date-format-element-ww.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM