我在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
我无法看到如何解决这个问题,因为“只有他们是整个月的会员”规则。
非常感谢任何帮助!
答案 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