根据 15 分钟的间隔获取计数

Chi*_*kar 3 sql-server sql-server-2008-r2 count date

我有一个包含通话记录的表:

tbl_calls

cl_Id
cl_StartDate
cl_endDate
Run Code Online (Sandbox Code Playgroud)

我传递两个参数@StartDate@EndDate给我的存储过程。

我的要求是在每 15 分钟的持续时间内获取通话记录的数量。

例如,如果:

@StartDate = '2015-11-16 00:00:00.000', 
@EndDate = '2015-11-16 23:59:00.000'
Run Code Online (Sandbox Code Playgroud)

输出应该是:

Date                        Count
2015-11-16 00:00:00.000      10(Count of startDate between '2015-11-16 00:00:00.000' AND '2015-11-16 00:15:00.000')
2015-11-16 00:15:00.000       7(Count of startDate between '2015-11-16 00:15:00.000' AND '2015-11-16 00:30:00.000')
2015-11-16 00:30:00.000      50(Count of startDate between '2015-11-16 00:30:00.000' AND '2015-11-16 00:45:00.000')

upto @EndDate
Run Code Online (Sandbox Code Playgroud)

我已经尝试了以下查询,但它不能正常工作。有一个更好的方法吗?

DECLARE @StartDate DATETIME = DATEADD(DAY,-1,GETUTCDATE()),
        @EndDate DATETIME = GETUTCDATE()

SELECT New 
FROM
    (SELECT 
         (CASE 
             WHEN cl_StartTime BETWEEN @StartDate AND 
                         DATEADD(MINUTE, 15, @StartDate) 
                THEN 1 
                ELSE 0 
          END) AS New 
     FROM          
         tbl_Calls WITH (NOLOCK)    
     WHERE 
         cl_StartTime BETWEEN @StartDate AND @EndDate) AS Inners 
GROUP BY 
    New
Run Code Online (Sandbox Code Playgroud)

如果您需要更多详细信息,请告诉我。

Han*_*non 7

这是“数字表”如何真正帮助获得所需结果的经典示例。

本质上,您创建了一个包含所需 15 分钟增量的表,然后加入您的表以获取每 15 分钟增量的总呼叫数。

例如,我对两个表都使用临时表。您可能希望将该#Intervals表永久化。

创建测试平台,并填充一些示例数据:

USE tempdb;

IF (OBJECT_ID('tempdb..#Calls') IS NOT NULL)
DROP TABLE #Calls;

CREATE TABLE #Calls
(
    CallID INT NOT NULL
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , CallStart DATETIME NOT NULL
    , CallEnd DATETIME NOT NULL
);

;WITH cte AS
(
    SELECT rn = ROW_NUMBER() OVER (ORDER BY o.object_id, o1.object_id)
        , rn1 = ROW_NUMBER() OVER (PARTITION BY o.object_id 
                                     ORDER BY o1.object_id)
    FROM sys.objects o, sys.objects o1
)
INSERT INTO #Calls (CallStart, CallEnd)
SELECT DATEADD(MINUTE, c.rn, DATEADD(DAY, -1, GETDATE()))
    , DATEADD(MINUTE, c.rn + c.rn1, DATEADD(DAY, -1, GETDATE()))
FROM cte c;

IF (OBJECT_ID('tempdb..#Intervals') IS NOT NULL)
DROP TABLE #Intervals;

CREATE TABLE #Intervals
(
    DateStart DATETIME NOT NULL
    , DateEnd DATETIME NOT NULL
);

;WITH cte AS
(
    SELECT TOP(35040) /* approx. number of 15 minute intervals in a year */
        rn = ROW_NUMBER() OVER (ORDER BY o.object_id, o1.object_id) * 15
    FROM sys.objects o
        , sys.objects o1
        , sys.objects o2
)
INSERT INTO #Intervals (DateStart, DateEnd)
SELECT DATEADD(MINUTE, c.rn, '2015-10-01T00:00:00')
    , DATEADD(MINUTE, c.rn + 15, '2015-10-01T00:00:00')
FROM cte c;
Run Code Online (Sandbox Code Playgroud)

显示两个表中的行:

SELECT *
FROM #Intervals i
ORDER BY i.DateStart;

SELECT *
FROM #Calls c
ORDER BY c.CallStart;
Run Code Online (Sandbox Code Playgroud)

连接两个表以获取 15 分钟日期范围之间的呼叫总数:

SELECT i.DateStart
    , i.DateEnd
    , TotalCalls = COUNT(1)
FROM #Calls c
    INNER JOIN #Intervals i ON c.CallStart >= i.DateStart
        AND c.CallStart < i.DateEnd
GROUP BY i.DateStart
    , i.DateEnd
ORDER BY i.DateStart;
Run Code Online (Sandbox Code Playgroud)

在我的测试平台上,我从三个select语句中得到以下结果:

在此处输入图片说明

查看对@Thofle 的回答的评论,您似乎希望查看所有时间间隔,即使在给定间隔内没有电话。为此,您可以简单地修改select查询以使用 aLEFT JOIN和行COUNT(...)Calls,例如:

SELECT i.DateStart
    , i.DateEnd
    , TotalCalls = COUNT(c.CallID)
FROM #Intervals i 
    LEFT JOIN #Calls c
        ON i.DateStart <= c.CallStart
            AND i.DateEnd > c.CallStart
GROUP BY i.DateStart
    , i.DateEnd
ORDER BY i.DateStart;
Run Code Online (Sandbox Code Playgroud)