如何生成4周的日期范围?

时间:2016-02-26 16:02:06

标签: sql oracle

我必须在固定日期后退和前进的4周(或28天)差距中生成1年的日期范围。例如,我有DATE'2016-02-20'。我需要生成以下内容。

开始日期=星期日,结束日期=星期六

No   Start_date  End_date
==== =========  =======
1   1/24/2016   2/20/2016
2   12/27/2015  1/23/2016
3   11/29/2015  12/26/2015
4   .....
13  2/22/2015   3/21/2015
14  1/25/2015   2/21/2015

但是,当2016年3月20日(星期日)到来时,它应添加 1. 2/21/2016 3/19/2016& 删除 14. 1/25/2015 2/21/2015 等等,每4周一次。

我已经写了下面的内容,但我需要帮助来迭代最小代码(如果可能的话)。

SELECT LEVEL,
  DATE '2016-02-20'-27*LEVEL-LEVEL+1 AS start_date,
  DATE '2016-02-20'-28*(LEVEL-1) AS end_date
FROM DUAL
Connect BY LEVEL < 15;

1 个答案:

答案 0 :(得分:2)

根据当前日期,您似乎希望拥有一年四周范围的滚动窗口。要做到这一点,您需要一个固定的已知期间开始(或结束)日期。挑选一个恰好是1月1日的你可以做到:

SELECT DATE '2012-01-01' + (28 * (LEVEL - 1)) AS start_date,
  DATE '2012-01-01' + (28 * LEVEL) - 1 AS end_date
FROM DUAL
CONNECT BY DATE '2012-01-01' + (28 * LEVEL) - 1 <= TRUNC(sysdate)

到目前为止,将找到54个时期。在3月21日,它将找到55个句点,等等。您只需要去年的那些,所以将其用作内联视图并限制范围:

SELECT ROW_NUMBER() OVER (ORDER BY start_date DESC) AS no, start_date, end_date
FROM (
  SELECT DATE '2012-01-01' + (28 * (LEVEL - 1)) AS start_date,
    DATE '2012-01-01' + (28 * LEVEL) - 1 AS end_date
  FROM DUAL
  CONNECT BY DATE '2012-01-01' + (28 * LEVEL) - 1 <= TRUNC(sysdate)
)
WHERE end_date >= ADD_MONTHS(TRUNC(sysdate), -12)
ORDER BY start_date DESC;

        NO START_DATE END_DATE 
---------- ---------- ----------
         1 01/24/2016 02/20/2016
         2 12/27/2015 01/23/2016
         3 11/29/2015 12/26/2015
...
        11 04/19/2015 05/16/2015
        12 03/22/2015 04/18/2015
        13 02/22/2015 03/21/2015

ROW_NUMBER()只会生成您的NO列,因为LEVEL现在的顺序错误。

如果您总是希望结果集中只有14行,则可以将ROW_NUMBER()移动到内联视图中:

SELECT no, start_date, end_date
FROM (
  SELECT ROW_NUMBER() OVER (ORDER BY LEVEL DESC) AS no,
    DATE '2012-01-01' + (28 * (LEVEL - 1)) AS start_date,
    DATE '2012-01-01' + (28 * LEVEL) - 1 AS end_date
  FROM DUAL
  CONNECT BY DATE '2012-01-01' + (28 * LEVEL) - 1 <= TRUNC(sysdate)
)
WHERE no <= 14
ORDER BY no;

        NO START_DATE END_DATE 
---------- ---------- ----------
         1 01/24/2016 02/20/2016
         2 12/27/2015 01/23/2016
         3 11/29/2015 12/26/2015
...
        12 03/22/2015 04/18/2015
        13 02/22/2015 03/21/2015
        14 01/25/2015 02/21/2015

 14 rows selected