Sql 日期范围之间的成员数据
我在SQL Server 2014中有一个名为[Membership]的表,其中包含个人成员数据和两个名为[member from date]和[member to date]的日期字段 我需要总结一下每月的会员情况。只有当某个会员是该整月的会员时,该会员才算是该月的会员 因此,例如,【自日期起的会员】为“2014-02-01”,而【截至日期止的会员】为“2015-03-01”的人士将计入2014年12月,但如果【截至日期止的会员】为“2014-12-25”,则不计入2014年12月 从2010年1月开始,我每个月都要总结一下,这个表中有数千名成员。结果需要与此类似:Sql 日期范围之间的成员数据,sql,sql-server,date,grouping,Sql,Sql Server,Date,Grouping,我在SQL Server 2014中有一个名为[Membership]的表,其中包含个人成员数据和两个名为[member from date]和[member to date]的日期字段 我需要总结一下每月的会员情况。只有当某个会员是该整月的会员时,该会员才算是该月的会员 因此,例如,【自日期起的会员】为“2014-02-01”,而【截至日期止的会员】为“2015-03-01”的人士将计入2014年12月,但如果【截至日期止的会员】为“2014-12-25”,则不计入2014年12月 从2010
Month Count
Jan 2010 3230
Feb 2010 3235
Mar 2010 3232
..
Dec 2016 6279
我不知道该怎么做,因为只有当他们是整月规则的会员时
任何帮助都将不胜感激 使用spt_值和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
借助月数表,可以非常轻松地处理此问题:
/* 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]
为什么您给出的示例不会出现在2015年3月的会员中?例如,如果我们计算2014年12月的会员人数,那么我将按[会员起始日期]=“2014-12-31”进行过滤。希望这能澄清问题。谢谢谢谢你,我发现这很容易理解,现在我想让它做什么就做什么。很高兴帮助@Baldy
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