【问题标题】:SQL to create table with weeks in period - having breaks at month's end (Oracle)SQL 来创建以周为周期的表 - 在月底休息(Oracle)
【发布时间】:2009-12-02 23:08:51
【问题描述】:

我需要创建一个结构如下的表:

日历周;周开始日期;周末结束日期

其中包含从 2007 年开始到当前一周的所有周。

特别之处在于,当月末在一周内时,该周被分成两部分 - 一条记录的开始日期是一周的开始日期,结束日期是一周的最后一天月,以及一个包含一周剩余日期的记录(开始日期是新月份的第一天,结束日期是一周的最后一天)。

示例(一周的开始是星期一):
calendar week; week start date; week end date; ... 2009 cW48; 23.11.2009; 29.11.2009 --"normal" week with 7 days, beginning monday and ending sunday 2009 cW49; 30.11.2009; 30.11.2009 --first part of the CW49, which ends at last day of the month 2009 cW49; 01.12.2009; 06.12.2009 --second part of the CW49, which begins at fist day of the new month 2009 cW50; 07.12.2009; 13.12.2009 --"normal" week, without a monthly break ...

如何在Oracle(SQL或PL SQL)中创建这样的表?

【问题讨论】:

    标签: sql oracle time plsql


    【解决方案1】:

    你可以像这样创建你的表:

    SQL> CREATE TABLE weeks AS
      2  WITH generator AS (
      3     SELECT DATE '2007-01-01' + LEVEL - 1 dt
      4       FROM dual
      5     CONNECT BY LEVEL <= SYSDATE - DATE '2007-01-01' + 1
      6  )
      7  SELECT to_char(dt, 'YYYY "cW"IW') "calendar week",
      8         dt "week start date",
      9         least(next_day(dt - 1, to_char(DATE '2007-01-07', 'DAY')),
     10               last_day(dt)) "week end date"
     11    FROM generator
     12   WHERE to_char(dt, 'D') = to_char(DATE '2007-01-01', 'D') -- only mondays
     13      OR to_char(dt, 'dd') = 1 --or first day of the month
     14  ;
    
    Table created
    SQL> SELECT *
      2    FROM weeks
      3   WHERE "week start date" BETWEEN DATE '2009-11-15' AND DATE '2009-12-15';
    
    calendar week week start date week end date
    ------------- --------------- -------------
    2009 cW47     16/11/2009      22/11/2009
    2009 cW48     23/11/2009      29/11/2009
    2009 cW49     30/11/2009      30/11/2009
    2009 cW49     01/12/2009      06/12/2009
    

    【讨论】:

      【解决方案2】:

      这是一个用于创建表的小型 PL/SQL 块。 如果需要,可以更改表名。

      -- create table weeks(year number, week number, b_date date, e_date date);
      
      DECLARE
          i  DATE;
          s  DATE;
          wk NUMBER;
          yr NUMBER;
      
          FUNCTION getweek(l DATE) RETURN NUMBER IS
          BEGIN
              -- !! week of year, iso standard, (31. dec can be on the first week of next year) !!
              RETURN to_char(l, 'IW');
          END;
      BEGIN
          i := to_date('2007-01-01', 'yyyy-mm-dd');
          s := i;
      
          DELETE weeks;
      
          WHILE i <= to_date('2009-12-31', 'yyyy-mm-dd') LOOP
      
              IF trunc(s, 'MONTH') <> trunc(i, 'MONTH') OR
                 getweek(s) <> getweek(i) THEN
      
                  wk := getweek(s);
                  yr := to_char(s, 'YYYY');
                  INSERT INTO weeks VALUES (yr, wk, s, i - 1);
      
                  s := i;
                  i := s;
              END IF;
      
              i := i + 1;
          END LOOP;
      
          i := i - 1;
      
          wk := getweek(s);
          yr := to_char(s, 'YYYY');
          INSERT INTO weeks VALUES (yr, wk, s, i);
      
          COMMIT;
      END;
      

      【讨论】:

        【解决方案3】:

        您可以这样创建表:

            create table weeks(cw, start_date, end_date)
            as
            select to_char(gen.d,'YYYY "cW"IW')
                 , min(gen.d)
                 , max(gen.d)
              from (
                     select to_date('01.01.2007','DD.MM.YYYY') + level -1 d
                       from dual
                    connect by level <= 1500 -- approx. number of days
                   ) gen
             group by
                   to_char(gen.d,'YYYY "cW"IW')
                 , to_char(gen.d,'YYYY MM IW')
            having min(gen.d) <= sysdate
        

        重点是使用IWMM格式掩码获取周数和月数,然后按两者分组。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-22
          • 2021-08-19
          • 2019-04-05
          相关资源
          最近更新 更多