2017-01-17 1 views
0

Ich habe eine Tabelle in SQL Server 2014 mit dem Namen [Mitgliedschaft] mit persönlichen Mitgliedsdaten und zwei Datumsfeldern mit dem Namen [Mitglied von Datum] und [Mitglied bis Datum].Mitgliedsdaten zwischen den Datumsbereichen

Ich muss die monatliche Mitgliedschaft zusammenfassen. Ein Mitglied wird nur in einem bestimmten Monat gezählt, wenn es sich um einen Mitglied für diesen ganzen Monat handelt.

So würde zum Beispiel eine Person mit [Mitglied von Datum] von "2014-02-01" und [Mitglied bis Datum] von '2015-03-01' im Monat Dezember 2014 gezählt werden, würde aber nicht sein, wenn das [Mitglied bis heute] beispielsweise "2014-12-25" war.

Ich muss jeden Monat bis Januar 2010 zusammenfassen und ich habe Tausende von Mitgliedern in dieser Tabelle. Die Ergebnisse müssen diese ähnlich aussehen:

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

Ich kann nicht sehen, wie dies funktioniert, weil die Regel „nur dann, wenn sie ein Mitglied für den ganzen Monat sind“.

Jede Hilfe wird am meisten geschätzt werden!

+0

warum das Beispiel, das Sie gaben nicht im Mitglied Mar.2015 sein würde? – LONG

+0

Wenn wir zum Beispiel die Mitgliedschaft für Dezember 2014 zählen, würde ich nach [Mitglied von Datum] <= '2014-12-01' und [Mitglied bis Datum]> = '2014-12-31' filtern. Hoffe das klärt sich. Vielen Dank! – Baldy

Antwort

1

Mit spt_values ​​und einer cte, um den Kalender zu generieren, ist hier ein Beispiel, das Mitglieder zählt.

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 
0

Mit Hilfe eines Monate Tabelle kann diese ziemlich leicht gehandhabt werden:

/* 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] 

Wenn Sie wirklich eine Monate Tabelle haben wollen nicht, Sie cte wie diese verwenden:

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] 
+0

Danke, ich fand das leicht zu verstehen und habe es so gemacht, wie ich es wollte. – Baldy

+0

Wir freuen uns, @Baldy zu helfen – SqlZim

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 
Verwandte Themen