web-dev-qa-db-ja.com

15分の間隔に基づいてカウントを取得する

コールレコードを含むテーブルがあります。

tbl_calls

cl_Id
cl_StartDate
cl_endDate

2つのパラメーターを渡しています@StartDateおよび@EndDateを私のストアドプロシージャに追加します。

私の要件は、15分間ごとの通話記録の数を取得することです。

たとえば、次の場合:

@StartDate = '2015-11-16 00:00:00.000', 
@EndDate = '2015-11-16 23:59:00.000'

出力は次のようになります。

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

次のクエリを試しましたが、正常に動作しません。これを行うより良い方法はありますか?

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

詳細が必要な場合はお知らせください。

2
Chirag Thakar

これは "Numbers table" が実際に必要な結果を得るのに役立つ典型的な例です。

基本的に、必要な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;
_

両方のテーブルの行を表示します。

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

SELECT *
FROM #Calls c
ORDER BY c.CallStart;
_

両方のテーブルを結合して、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;
_

私のテストプラットフォームでは、3つのselectステートメントから次の結果が得られます。

enter image description here

@ -Thofleの回答で あなたのコメント を見ると、指定された間隔中に呼び出しがなかった場合でも、すべての時間間隔を確認したいようです。これを行うには、selectクエリを変更して_LEFT 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;
_
6
Max Vernon

このような何かがうまくいくかもしれません

SELECT 
  count(1)
  ,DATEADD(MINUTE,(DATEPART(MINUTE, cl_StartDate) / 15)*15,(DATEADD(HOUR, DATEDIFF(HOUR, 0, cl_StartDate), 0)))
FROM tbl_Calls
WHERE 
  cl_StartTime BETWEEN @StartDate AND @EndDate
GROUP BY 
  DATEADD(MINUTE,(DATEPART(MINUTE, cl_StartDate) / 15)*15,(DATEADD(HOUR, DATEDIFF(HOUR, 0, cl_StartDate), 0)))


四半期を取得するには、これは0〜3の値になります。 15を掛けて0、15、30、45を取得します。

DATEPART(MINUTE, date_recorded) / 15 


cl_StartTimeを丸1時間に切り捨てます。

DATEADD(HOUR, DATEDIFF(HOUR, 0, date_recorded), 0)


次に、クエリのようにそれを追加して、正しいタイムスタンプを取得し、それによってグループ化します。

1
thofle