SQL Person by month数据

时间:2017-02-19 05:17:16

标签: sql sql-server tsql

我有一个

的数据集
Name|ID|Start_DATE|END_DATE

我想在活跃的几个月里休息一下。

示例:

Bob Smith|1001|2016-12-01|2017-02-18

将返回日期之间列出的所有月份

Bob Smith|1001|2016-12-01
Bob Smith|1001|2017-01-01
Bob Smith|1001|2017-02-02

根据我发现的日期,我一直在计划一些数据。一旦我弄清楚基本查询,我还需要处理列为9999-12-31的活跃员工。

declare @startDate date;
declare @endDate date;

select @startDate = '20100101';
select @endDate = '20150531';

with dateRange as
(
  select dt = dateadd(mm, 0, @startDate)
  where dateadd(mm, 0, @startDate) < @endDate
  union all
  select dateadd(mm, 1, dt)
  from dateRange
  where dateadd(mm, 1, dt) < @endDate
)
select *
from dateRange

有没有更好的方法来处理它?<​​/ p>

1 个答案:

答案 0 :(得分:0)

假设我理解这个问题,这是一种方法:

首先,创建并填充样本表(在将来的问题中将此步骤保存起来)

DECLARE @T AS TABLE
(
    Name varchar(20), 
    ID int, 
    Start_DATE date, 
    END_DATE date
)
INSERT INTO @T VALUES
('Bob Smith', 1001, '2016-12-01', '2017-02-18')

您的问题中的DateRange日历cte,其中包含适合样本数据的日期:

declare @startDate date;
declare @endDate date;

select @startDate = '20150101';
select @endDate = '20200531';

with dateRange as
(
  select dt = dateadd(mm, 0, @startDate)
  where dateadd(mm, 0, @startDate) < @endDate
  union all
  select dateadd(mm, 1, dt)
  from dateRange
  where dateadd(mm, 1, dt) < @endDate
)

查询:

SELECT  Name,
        ID, 
        CONVERT(char(12), Start_DATE, 107) As StartDate, -- just to see it clearly in the results
        CONVERT(char(12), END_DATE, 107) As EndDate, -- just to see it clearly in the results
        CONVERT(char(12), dt, 107) As ActiveMonth

FROM @T
INNER JOIN dateRange ON dt >= Start_DATE AND dt < END_DATE

结果:

Name        ID      StartDate       EndDate         ActiveMonth
Bob Smith   1001    Dec 01, 2016    Feb 18, 2017    Dec 01, 2016
Bob Smith   1001    Dec 01, 2016    Feb 18, 2017    Jan 01, 2017
Bob Smith   1001    Dec 01, 2016    Feb 18, 2017    Feb 01, 2017
顺便说一句,有一种更好的方法来创建一个日历cte,使用数字(或计数)表。 here a demo.