2015-12-02 140 views
1

我有一个表:甲骨文 - 查找每月,每季度和每年的日期

table1的

start  end 
1/jan/2012 15/jan/2012 
1/feb/2013 5/april/2013 

我需要找出所有可能的月度,季度和年度的时间表。例如。

1) 1/JAN/2012 15/JAN/2012

将落入之间:

1/jan/2012 31/jan/2012 
1/jan/2012 31/march/2012 
1/jan/2012 31/dec/2012 

2) 1 /二月/ 2013 5月/ 4月/ 2013

将介于:

1/feb/2013 28/feb/2013 
1/march/2013 31/march/2013 
1/april/2013 30/april/2013 
1/jan/2013 31/march/2013 
1/april/2013 30/june/2013 
1/jan/2013 31/dec/2013 

是否有可能通过SQL查询到g等所有可能的日期组合?

+0

他们是日期/时间戳还是字符串? – Matt

+1

问题有点暧昧。请详细说明。 –

+0

问题不清楚。你想要一个sql语句吗?请举个例子。 – Jack

回答

1
WITH date_range AS (
    SELECT TO_DATE('2012-01-01', 'YYYY-MM-DD') AS start_date, TO_DATE('2012-01-15', 'YYYY-MM-DD') AS end_date FROM DUAL 
    UNION 
    SELECT TO_DATE('2012-02-01', 'YYYY-MM-DD') AS start_date, TO_DATE('2012-04-05', 'YYYY-MM-DD') AS end_date FROM DUAL 
), monthly_range AS (
    SELECT dr.start_date 
     , dr.end_date 
     , 'Monthly' AS range_type 
     , ADD_MONTHS(TRUNC(dr.start_date, 'MM'), LEVEL - 1) AS month_start 
     , ADD_MONTHS(LAST_DAY(dr.start_date), LEVEL - 1) AS month_end 
    FROM date_range dr 
    CONNECT BY LEVEL <= CEIL(MONTHS_BETWEEN(dr.end_date, dr.start_date)) 
), quarterly_range AS (
    SELECT 
      dr.start_date 
     , dr.end_date 
     , 'Quarterly' AS range_type 
     , ADD_MONTHS(TRUNC(dr.start_date, 'MM'), (LEVEL - 1) * 3) AS range_start 
     , ADD_MONTHS(TRUNC(dr.start_date, 'MM'), LEVEL * 3) - 1 AS range_end 

    FROM date_range dr 
    CONNECT BY LEVEL <= CEIL(MONTHS_BETWEEN(dr.end_date, dr.start_date)/3) 
), yearly_range AS (
    SELECT 
      dr.start_date 
     , dr.end_date 
     , 'Yearly' AS range_type 
     , ADD_MONTHS(TRUNC(dr.start_date, 'MM'), (LEVEL - 1) * 12) AS range_start 
     , ADD_MONTHS(TRUNC(dr.start_date, 'MM'), LEVEL * 12) - 1 AS range_end 
    FROM date_range dr 
    CONNECT BY LEVEL <= CEIL(MONTHS_BETWEEN(dr.end_date, dr.start_date)/12) 
) 
SELECT mr.* FROM monthly_range mr 
UNION 
SELECT qr.* FROM quarterly_range qr 
UNION 
SELECT yr.* FROM yearly_range yr 
ORDER BY 1,2,3,4; 
+0

这给出了完美的结果,谢谢! – dang

2

希望它能帮助:

-- test data 
with table1 as 
(select 1 as id, 
     to_date('20120101', 'YYYYMMDD') as start_dt, 
     to_date('20120115', 'YYYYMMDD') as end_dt 
    from dual 
    union all 
    select 2 as id, 
     to_date('20130201', 'YYYYMMDD') as start_dt, 
     to_date('20130405', 'YYYYMMDD') as end_dt 
    from dual), 

-- get sequences in range [0..max date interval-1] 
idx_tab as 
(select level - 1 as idx 
    from dual 
    connect by level < (select max(end_dt - start_dt) from table1)), 

-- expand interval [start_dt; end_dt] by day 
dt_tb as 
(select t.id, t.start_dt, t.end_dt, t.start_dt + i.idx as dt 
    from table1 t, idx_tab i 
    where t.start_dt + idx <= t.end_dt) 

select 'Month-' || to_char(dt, 'YYYY-MM'), id, start_dt, end_dt 
    from dt_tb 
union 
select 'Quarter-' || to_char(dt, 'YYYY-Q'), id, start_dt, end_dt 
    from dt_tb 
union 
select 'Year-' || to_char(dt, 'YYYY'), id, start_dt, end_dt 
    from dt_tb 
order by 1, 2; 
+0

这个工作,但是,我需要每月,每季度和每年的START和END日期。 – dang

+0

好的,这应该很容易调整。替换''Month-'||通过'trunc(dt,'MON'),trunc(add_months(dt,1),'MON')-1'等,to_char(dt,'YYYY-MM')'等。 –

1

SQL Fiddle

查询1

WITH dates (date_start, date_end) AS (
    SELECT DATE '2013-02-01', DATE '2013-04-05' FROM DUAL 
) 
SELECT 'M' AS period, 
     ADD_MONTHS(TRUNC(date_start, 'MM'), LEVEL - 1) AS range_start, 
     ADD_MONTHS(TRUNC(date_start, 'MM'), LEVEL) - INTERVAL '1' DAY AS range_end 
FROM dates 
CONNECT BY 
     ADD_MONTHS(TRUNC(date_start, 'MM'), LEVEL - 1) <= TRUNC(date_end, 'MM') 
UNION ALL 
SELECT 'Q' AS period, 
     ADD_MONTHS(TRUNC(date_start, 'Q'), 3 * (LEVEL - 1)) AS range_start, 
     ADD_MONTHS(TRUNC(date_start, 'Q'), 3 * LEVEL) - INTERVAL '1' DAY AS range_end 
FROM dates 
CONNECT BY 
     ADD_MONTHS(TRUNC(date_start, 'Q'), 3 * (LEVEL - 1)) <= TRUNC(date_end, 'Q') 
UNION ALL 
SELECT 'Y' AS period, 
     ADD_MONTHS(TRUNC(date_start, 'Y'), 12 * (LEVEL - 1)) AS range_start, 
     ADD_MONTHS(TRUNC(date_start, 'Y'), 12 * LEVEL) - INTERVAL '1' DAY AS range_end 
FROM dates 
CONNECT BY 
     ADD_MONTHS(TRUNC(date_start, 'Y'), 12 * (LEVEL - 1)) <= TRUNC(date_end, 'Y') 

Results

| PERIOD |    RANGE_START |     RANGE_END | 
|--------|----------------------------|----------------------------| 
|  M | February, 01 2013 00:00:00 | February, 28 2013 00:00:00 | 
|  M | March, 01 2013 00:00:00 | March, 31 2013 00:00:00 | 
|  M | April, 01 2013 00:00:00 | April, 30 2013 00:00:00 | 
|  Q | January, 01 2013 00:00:00 | March, 31 2013 00:00:00 | 
|  Q | April, 01 2013 00:00:00 |  June, 30 2013 00:00:00 | 
|  Y | January, 01 2013 00:00:00 | December, 31 2013 00:00:00 | 
+0

aah,very good - beat我给它 – ninesided

+0

它不会以月份结束。它不应该是下个月的第一次约会。 – dang

+0

简单修正 - 在'range_end'上使用'-1'或' - INTERVAL'1'DAY'。 – MT0

相关问题