按截止日期划分期间

时间:2018-02-20 11:41:17

标签: sql sql-server-2008

请您查看以下任务?

我有以下数据集:

HERE

以下是此数据的脚本:

;with dataset AS (
    select 'EMP01' AS EMP_ID,CAST('2018-01-01' AS DATE) AS PERIOD_START,CAST('2018-01-31' AS DATE) AS PERIOD_END,CAST('2018-01-07' AS DATE) AS CUT_DATE
    UNION
    select 'EMP01' AS EMP_ID,CAST('2018-01-01' AS DATE) AS PERIOD_START,CAST('2018-01-31' AS DATE) AS PERIOD_END,CAST('2018-01-15' AS DATE) AS CUT_DATE
    UNION
    select 'EMP02' AS EMP_ID,CAST('2018-01-01' AS DATE) AS PERIOD_START,CAST('2018-01-31' AS DATE) AS PERIOD_END,CAST('2018-01-09' AS DATE) AS CUT_DATE
)
select *
from dataset

我需要将这些期间(PERIOD_START和PERIOD_END)除以CUT_DATE(不包括那些期间的截止日期)切割日期的数量可以是任意的(3,5,8等)。

期望上述数据集的结果是:

enter image description here

2 个答案:

答案 0 :(得分:0)

这是你需要的吗?

with dataset AS (
    select 'EMP01' AS EMP_ID,CAST('2018-01-01' AS DATE) AS PERIOD_START,CAST('2018-01-31' AS DATE) AS PERIOD_END,CAST('2018-01-07' AS DATE) AS CUT_DATE
    UNION
    select 'EMP01' AS EMP_ID,CAST('2018-01-01' AS DATE) AS PERIOD_START,CAST('2018-01-31' AS DATE) AS PERIOD_END,CAST('2018-01-15' AS DATE) AS CUT_DATE
    UNION
    select 'EMP02' AS EMP_ID,CAST('2018-01-01' AS DATE) AS PERIOD_START,CAST('2018-01-31' AS DATE) AS PERIOD_END,CAST('2018-01-09' AS DATE) AS CUT_DATE
)
select emp_id, period_start period_start, cut_date - 1 period_end from dataset
union all
select emp_id, cut_date + 1 period_start, period_end period_end from dataset;

答案 1 :(得分:0)

这可以使用日期表和窗口函数来实现。如果您没有日期表,则可以使用下面脚本中的前两个cte表为此查询生成一个:

declare @t table(emp_id nvarchar(10)
                ,period_start date
                ,period_end date
                ,cut_date date
                );
insert into @t values
 ('EMP01','20180101','20180131','2018-01-07')
,('EMP01','20180101','20180131','2018-01-15')
,('EMP02','20180101','20180131','2018-01-09')
;

declare @s date = (select min(period_start) as d from @t);
declare @e date = (select max(period_end) as d from @t);

              -- Generate a table of 10 rows
with t(t) as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1)
    ,d(d) as (select top (select datediff(day,@s,@e)+1) dateadd(day,row_number() over (order by (select null))-1,@s) from t t1,t t2,t t3,t t4,t t5)  -- CROSS JOIN 10 rows together 5 times for a maximum of 10*10*10*10*10 = 100,000 rows
    ,c    as (select d.d
                    ,t.emp_id
                    ,t.period_start
                    ,t.period_end
                    ,sum(case when t.cut_date = d.d then 1 else 0 end) over (partition by t.emp_id order by d.d) as p
              from @t as t
                  left join d
                      on(d.d between t.period_start and t.period_end)
             )
select emp_id
      ,min(case when period_start = d then d else dateadd(day,1,d) end) as period_start
      ,max(d) as period_end
from c
group by emp_id
        ,p
order by emp_id
        ,period_start

输出:

+--------+--------------+------------+
| emp_id | period_start | period_end |
+--------+--------------+------------+
| EMP01  | 2018-01-01   | 2018-01-06 |
| EMP01  | 2018-01-08   | 2018-01-14 |
| EMP01  | 2018-01-16   | 2018-01-31 |
| EMP02  | 2018-01-01   | 2018-01-08 |
| EMP02  | 2018-01-10   | 2018-01-31 |
+--------+--------------+------------+