コールレコードを含むテーブルがあります。
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
詳細が必要な場合はお知らせください。
これは "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
ステートメントから次の結果が得られます。
@ -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;
_
このような何かがうまくいくかもしれません
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)
次に、クエリのようにそれを追加して、正しいタイムスタンプを取得し、それによってグループ化します。