我有一张桌子:
表1
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 / feb / 2013 5 / april / 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查询来获取所有可能的日期组合?
答案 0 :(得分: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;
答案 1 :(得分:1)
查询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 |
答案 2 :(得分: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;