SQL:根据两个日期之间的月份为一条记录创建多行

时间:2018-08-24 03:44:53

标签: sql netezza

我的表具有以下记录,分别记录不同的ID和不同的开始和结束日期
ID,开始日期,结束日期
1,2017-02-14,2018-11-05

我想使用日期维度表编写一个不包含的SQL,该表提供以下输出:基本上,从开始到结束日期之间每个月都有一条记录。

1, 2017, 02
1, 2017, 03
1, 2017, 04
1, 2017, 05
1, 2017, 06
1, 2017, 07
1, 2017, 08
1, 2017, 09
1, 2017, 10
1, 2017, 11
1, 2017, 12
1, 2018, 01
1, 2018, 02
1, 2018, 03
1, 2018, 04
1, 2018, 05
1, 2018, 06
1, 2018, 07
1, 2018, 09
1, 2018, 10
1, 2018, 11

3 个答案:

答案 0 :(得分:1)

这就是我所做的,它像一种魅力:

-- sample data  
WITH table_data
AS (
    SELECT 1 AS id
        ,cast('2017-08-14' AS DATE) AS start_dt
        ,cast('2018-12-16' AS DATE) AS end_dt

UNION ALL

SELECT 2 AS id
    ,cast('2017-09-14' AS DATE) AS start_dt
    ,cast('2019-01-16' AS DATE) AS end_dt
)

-- find minimum date from the data  
,starting_date (start_date)
AS (
SELECT min(start_dt)
FROM TABLE_DATA
)

--get all months between min and max dates  
,all_dates
AS (
SELECT last_day(add_months(date_trunc('month', start_date), idx * 1)) month_date
FROM starting_date
CROSS JOIN _v_vector_idx
WHERE month_date <= add_months(start_date, abs(months_between((
                    SELECT min(start_dt) FROM TABLE_DATA), (SELECT max(end_dt) FROM TABLE_DATA))) + 1)
ORDER BY month_date
)
SELECT id  
,extract(year FROM month_date)  
,extract(month FROM month_date)  
,td.start_dt  
,td.end_dt  
FROM table_data td  
INNER JOIN all_dates ad  
    ON ad.month_date > td.start_dt  
        AND ad.month_date <= last_day(td.end_dt)  
ORDER BY 1  
    ,2  

答案 1 :(得分:0)

您必须生成日期,然后从中选择年份和月份

select distinct year(date),month( date) from
(select  * from (
select 
 date_add('2017-02-14 00:00:00.000', INTERVAL n5.num*10000+n4.num*1000+n3.num*100+n2.num*10+n1.num DAY ) as date 
  from
(select 0 as num
   union all select 1
   union all select 2
   union all select 3
   union all select 4
   union all select 5
   union all select 6
   union all select 7
   union all select 8
   union all select 9) n1,
(select 0 as num
   union all select 1
   union all select 2
   union all select 3
   union all select 4
   union all select 5
   union all select 6
   union all select 7
   union all select 8
   union all select 9) n2,
(select 0 as num
   union all select 1
   union all select 2
   union all select 3
   union all select 4
   union all select 5
   union all select 6
   union all select 7
   union all select 8
   union all select 9) n3,
(select 0 as num
   union all select 1
   union all select 2
   union all select 3
   union all select 4
   union all select 5
   union all select 6
   union all select 7
   union all select 8
   union all select 9) n4,
(select 0 as num
   union all select 1
   union all select 2
   union all select 3
   union all select 4
   union all select 5
   union all select 6
   union all select 7
   union all select 8
   union all select 9) n5
) a
where date >'2017-02-14 00:00:00.000' and date < '2018-11-05'
) as t

答案 2 :(得分:0)

请使用以下查询示例:

set @start_date = '2017-02-14';
set @end_date = LAST_DAY('2018-11-05');


WITH RECURSIVE date_range AS
(
select MONTH(@start_date) as month_, YEAR(@start_date) as year_, DATE_ADD(@start_date, INTERVAL 1 MONTH) as next_month_date
UNION
SELECT MONTH(dr.next_month_date) as month_, YEAR(dr.next_month_date) as year_, DATE_ADD(dr.next_month_date, INTERVAL 1 MONTH) as next_month_date
FROM date_range dr
where next_month_date <= @end_date
)
select month_, year_ from date_range 
order by next_month_date desc