我试图找到给定时期内的成员总数。说我有以下数据:
member_id start_date end_date
1 9/1/2013 12/31/2013
2 10/1/2013 11/12/2013
3 12/1/2013 12/31/2013
4 5/1/2012 8/5/2013
5 9/1/2013 12/31/2013
6 7/1/2013 12/31/2013
7 6/6/2012 12/5/2013
8 10/1/2013 12/31/2013
9 7/8/2013 12/31/2013
10 1/1/2012 11/5/2013
在SQL中,我需要创建一个报告,列出一年中每个月的成员数量。在这种情况下,如下所示:
Date Members Per Month
Jan-12 1
Feb-12 1
Mar-12 1
Apr-12 1
May-12 2
Jun-12 3
Jul-12 3
Aug-12 3
Sep-12 3
Oct-12 3
Nov-12 3
Dec-12 3
Jan-13 3
Feb-13 3
Mar-13 3
Apr-13 3
May-13 3
Jun-13 3
Jul-13 5
Aug-13 4
Sep-13 6
Oct-13 8
Nov-13 6
Dec-13 6
所以从1月12日(成员身份10)只有1名成员,直到5月12日成员身份4加入计数2,依此类推。
日期范围可以全部结束,因此我无法指定具体日期,但是按月计算,这意味着即使有人以12-1结束,也会认为该日期为12月。
答案 0 :(得分:0)
这应该可以解决问题
with datesCte(monthStart,monthEnd) as
(
select cast('20120101' as date) as monthStart, cast('20120131' as date) as monthEnd
union all
select DATEADD(MONTH, 1, d.monthStart), dateadd(day, -1, dateadd(month, 1, d.monthStart))
from datesCte as d
where d.monthStart < '20140101'
)
select *
from datesCte as d
cross apply
(
select count(*) as cnt
from dbo.MemberDates as m
where m.startDate <= d.monthEnd and m.endDate > d.monthStart
) as x
order by d.monthStart
答案 1 :(得分:0)
我能够创建以下能够完成我需要的存储过程:
USE [ValueBasedSandbox]
GO
/****** Object: StoredProcedure [dbo].[sp_member_count_per_month] Script Date: 01/08/2015 12:02:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Create date: 2015-08-01
-- Description: Find the counts per a given date passed in
-- =============================================
CREATE PROCEDURE [dbo].[sp_member_count_per_month]
-- Add the parameters for the stored procedure here
@YEAR int
, @ENDYEAR int
AS
DECLARE @FIRSTDAYMONTH DATETIME
DECLARE @LASTDAYMONTH DATETIME
DECLARE @MONTH INT = 1;
--Drop the temporary holding table if exists
IF OBJECT_ID('tempdb.dbo.##TEMPCOUNTERTABLE', 'U') IS NOT NULL
DROP TABLE dbo.##TEMPCOUNTERTABLE
CREATE TABLE dbo.##TEMPCOUNTERTABLE (
counter INT
, start_date DATETIME2
, end_date DATETIME2
)
--Perform this loop for each year desired
WHILE @YEAR <= @ENDYEAR
BEGIN
--Perform for each month of the year
WHILE (@MONTH <= 12)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET @FIRSTDAYMONTH = DATEADD(MONTH, @MONTH - 1, DATEADD(YEAR, @YEAR-1900, 0))
SET @LASTDAYMONTH = DATEADD(MONTH, @MONTH, DATEADD(YEAR, @YEAR-1900, 0)-1)
INSERT INTO dbo.##TEMPCOUNTERTABLE(counter, start_date, end_date)
SELECT COUNT(*) AS counter
, @FIRSTDAYMONTH AS start_date
, @LASTDAYMONTH AS end_date
FROM dbo.member_table
WHERE start_date <= @LASTDAYMONTH
AND end_date >= @FIRSTDAYMONTH
--Increment through all the months of the year
SET @MONTH = @MONTH + 1
END -- End Monthly Loop
--Reset Month counter
SET @MONTH = 1
--Increment the desired years
SET @YEAR = @YEAR + 1
END -- End Yearly Loop
--Display the results
SELECT *
FROM dbo.##TEMPCOUNTERTABLE
-- Drop the temp table
IF OBJECT_ID('tempdb.dbo.##TEMPCOUNTERTABLE', 'U') IS NOT NULL
DROP TABLE dbo.##TEMPCOUNTERTABLE
GO