查找特定时间段内的SQL总数

时间:2015-01-08 18:05:12

标签: tsql count

我试图找到给定时期内的成员总数。说我有以下数据:

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月。

2 个答案:

答案 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
相关问题