会员日期范围之间的数据

时间:2017-01-17 20:08:13

标签: sql sql-server date grouping

我在SQL Server 2014中有一个名为[Membership]的表,其中包含个人成员数据和两个名为[member from date]和[member to date]的日期字段。

我需要总结月度会员资格。只有成员在整个月内成为会员,才会在某个月内计算会员。

例如,2014年12月1日[2014-02-01成员]和[2015-03-01成员]成员的人将在2014年12月计算,但不会如果[迄今为止的成员]是'2014-12-25'。

我需要在每个月回顾到2010年1月的总结,我在这个表中有成千上万的成员。结果需要与此类似:

Month      Count
Jan 2010   3230
Feb 2010   3235
Mar 2010   3232
..
Dec 2016   6279

我无法看到如何解决这个问题,因为“只有他们是整个月的会员”规则。

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:1)

使用spt_values和cte生成日历,这是一个计算成员数的例子。

declare @members table (member int, start_date date, end_date date)
insert @members select 1, '2015-12-15', '2017-01-15'
insert @members select 2, '2016-01-15', '2016-12-15'
insert @members select 3, '2016-03-01', '2016-10-31'

declare @cal_from datetime = '2016-01-01';
declare @cal_to datetime = '2016-12-31';

with calendar_cte as (
    select   top (datediff(month, @cal_from, @cal_to) + 1)
             [Month] = month(dateadd(month, number, @cal_from))
           , [Year]  = year(dateadd(month, number, @cal_from))
           , [Start] = dateadd(month, number, @cal_from)
           , [End]   = dateadd(day, -1, dateadd(month, number + 1, @cal_from))
    from     [master].dbo.spt_values
    where    [type] = N'P'
    order by number
)
select [Month]
     , [Year]
     , [Count] = (select count(*) 
                  from   @members 
                  where  start_date <= [Start] 
                         and end_date >= [End])
from   calendar_cte

答案 1 :(得分:0)

借助Months表,可以非常轻松地处理:

  /* creating a months table */

create table dbo.Months([Month] date primary key, MonthEnd date);

declare @StartDate     date = '20100101'
       ,@NumberOfYears int  = 30;

insert dbo.Months([Month],MonthEnd)
  select top (12*@NumberOfYears) 
      [Month] = dateadd(month, row_number() over (order by number) -1, @StartDate)
      , MonthEnd = dateadd(day,-1,
            dateadd(month, row_number() over (order by number), @StartDate)
            )
    from master.dbo.spt_values;

    /* the query */

select [Month], [Count]=count(*)
  from dbo.Months mo
    inner join dbo.[Membership] me on 
    /* Member since the start of the month */
            me.MemberFromDate >= mo.[Month]  
    /* Member for the entire month being counted */
        and me.MemberToDate   > mo.[MonthEnd] 
  group by [Month]
  order by [Month]

如果你真的不想要一个月份表,你可以使用这样的cte

declare @StartDate     date = '20100101'
       ,@NumberOfYears int  = 30;

;with Months as (
select top (12*@NumberOfYears) 
    [Month] = dateadd(month, row_number() over (order by number) -1, @StartDate)
    , MonthEnd = dateadd(day,-1,
          dateadd(month, row_number() over (order by number), @StartDate)
          )
  from master.dbo.spt_values
)

    /* the query */

select [Month], [Count]=count(*)
  from Months mo
    inner join dbo.[Membership] me on 
    /* Member since the start of the month */
            me.MemberFromDate >= mo.[Month]  
    /* Member for the entire month being counted */
        and me.MemberToDate   > mo.[MonthEnd] 
  group by [Month]
  order by [Month]

答案 2 :(得分:0)

create table members(name varchar(50),fromdate datetime, todate datetime)
go
create table months(firstday datetime)
go
insert members values('Joe','2014-02-01','2015-03-25'),('Jon','2014-03-12','2015-01-12')

declare @date datetime = '2000-01-01'
while (@date < '2016-01-01')
begin
  insert into months values( @date )
  select @date = dateadd(month,1,@date)
end

with MyCTE(date) as
(   select left(convert(varchar, firstday, 120),7)
    from members m
    join months d on d.firstday > m.fromdate and d.firstday < datefromparts(year(m.todate),month(m.todate),1)
)
select date as 'month', count(*) as 'count'
from MyCTE
group by date