Oracle SQL查询/过程列出两个日期之间的月/季度

时间:2018-01-22 20:18:01

标签: sql oracle

我有一个要求

START_DATE : 03/01/2018
END_DATE : 28/12/2018

我需要一个查询,列出这两个日期之间的所有月份开始日期和结束日期,如下所示

StartMonth   EndMonth
03/01/2018  31/01/2018
01/02/2018  28/01/2018
01/03/2018  31/03/2018
01/04/2018  30/04/2018
01/05/2018  31/05/2018
01/06/2018  30/06/2018
01/07/2018  31/07/2018
01/08/2018  31/08/2018
01/09/2018  30/09/2018
01/10/2018  31/10/2018
01/11/2018  30/11/2018
01/12/2018  28/12/2018

我还需要一个查询,列出这两个日期之间所有季度的开始日期和结束日期,如下所示

StartQuarter EndQuarter
03/01/2018   31/03/2018
01/04/2018   30/06/2018
01/07/2018   30/09/2018
01/10/2018   28/12/2018

3 个答案:

答案 0 :(得分:1)

这些应该有用。

几个月:

    select greatest(:start_date, trunc(add_months( :start_date, level - 1), 'MON')) as startmonth,
           least(:end_date, last_day(add_months( :start_date, level - 1))) as endmonth
      from dual
connect by level <= trunc(months_between(trunc( :end_date, 'MON'), trunc( :start_date, 'MON'))) + 1;

对于季度:

    select greatest(:start_date, trunc(add_months( :start_date, 3 * (level - 1)), 'Q')) as startmonth,
           least(:end_date, last_day(add_months( :start_date, 3 * (level - 1) + 2))) as endmonth
      from dual
connect by level <= trunc(months_between(trunc( :end_date, 'Q'), trunc( :start_date, 'Q'))) / 3 + 1;

其中:start_date和:end_date是您的开始和结束日期。

答案 1 :(得分:0)

这里的变体并不限于任何特定的范围长度:

SELECT TO_CHAR(GREATEST(
         LAST_DAY(ADD_MONTHS(:start_date, LEVEL - 2)) + 1,
         :start_date
       ), 'dd/mm/yyyy') AS StartMonth,
       TO_CHAR(LEAST(
         :end_date, 
         LAST_DAY(ADD_MONTHS(:start_date, LEVEL - 1))
       ), 'dd/mm/yyyy') AS EndMonth
FROM dual
CONNECT BY LAST_DAY(ADD_MONTHS(:start_date, LEVEL - 1)) <= LAST_DAY(:end_date);
编辑:修正开始日期范围后,它看起来非常像接受的答案,使用不同的日期算术方式。对于每季度,@ GriffeyDog使用TRUNC可能是最好的选择。

答案 2 :(得分:0)

这是一个生成月度条目的CTE(公用表表达式):

WITH
    aset
    AS
        (SELECT DATE '2018-01-03' start_month, DATE '2018-12-28' last_month
           FROM DUAL),
    bset (start_month, end_month, last_month)
    AS
        (SELECT start_month, LEAST (ADD_MONTHS (TRUNC (start_month, 'MM'), 1) - 1, last_month) end_month, last_month
           FROM aset
         UNION ALL
         SELECT ADD_MONTHS (TRUNC (start_month, 'MM'), 1)
              , LEAST (ADD_MONTHS (start_month, 2) - 1, last_month)
              , last_month
           FROM bset
          WHERE end_month < last_month)
SELECT start_month, end_month
  FROM bset;


START_MONTH END_MONTH
----------- ---------
03-JAN-18   31-JAN-18
01-FEB-18   02-MAR-18
01-MAR-18   31-MAR-18
01-APR-18   30-APR-18
01-MAY-18   31-MAY-18
01-JUN-18   30-JUN-18
01-JUL-18   31-JUL-18
01-AUG-18   31-AUG-18
01-SEP-18   30-SEP-18
01-OCT-18   31-OCT-18
01-NOV-18   30-NOV-18
01-DEC-18   28-DEC-18