データベースにstatisticsを作成するようにプロシージャを変更する必要があります。
これらの統計を作成するために必要なすべてのデータを含む一時テーブルを取得しました。
関連するすべてのアクションが含まれていますFormIdNb作業単位NumCavalier 1日で:
-- Every action from all units will be stored in this temp table
-- DateHeure = Time of action
-- NumCavalier = ID of working unit
-- FormIdNb = Action type
CREATE TABLE #tmp_DailyMissions (
DateHeure datetime,
NumCavalier nchar(3),
FormIdNb int
)
INSERT INTO #tmp_DailyMissions
SELECT DateHeure, Cavalier.NumCavalier, FormIdNb
FROM ECN4, Cavalier
WHERE (DateHeure BETWEEN @StartTime AND @EndTime) AND (Cavalier.Terminal = @terminal) AND (Cavalier.NumCavalier = ECN4.NumCavalier)
この一時テーブルには、すべての作業ユニットが1日で行ったすべてのアクションが格納されます(ロギングシステムと同様)。
FormIdNbの重要な値は次のとおりです。
FormIdNb> 3 ==>作業ユニットはアクティブでした
FormIdNb = 3 ==>作業ユニットはアイドル状態でした
FormIdNb <3 ==>作業ユニットは非アクティブでした
私が今受け取ったリクエスト(@AndriyMのおかげで)は、[〜#〜] active [〜#〜]、[〜#〜]であった作業ユニットの数を返しますアイドル[〜#〜]および[〜#〜]非アクティブ[〜#〜] 1日の各時間間隔(15分):
WITH time_cte(StartTime, EndTime) AS
(
SELECT
StartTime = @starttime,
EndTime = DATEADD(mi, 15, @starttime)
UNION ALL
SELECT
EndTime,
DATEADD(mi, 15, EndTime)
FROM
time_cte
WHERE
EndTime < @EndTime
)
SELECT
t.StartTime,
ActiveUnitCount = COUNT(DISTINCT(CASE WHEN d.FormIdNb > 3 THEN d.NumCavalier END)),
IdleUnitCount = COUNT(DISTINCT(CASE WHEN d.FormIdNb = 3 THEN d.NumCavalier END)),
InactiveUnitCount = COUNT(DISTINCT(CASE WHEN d.FormIdNb < 3 THEN d.NumCavalier END))
FROM
time_cte AS t
LEFT OUTER JOIN #tmp_DailyMissions AS d
ON d.DateHeure >= t.StartTime
AND d.DateHeure < t.EndTime
GROUP BY
t.StartTime
;
問題は、上で述べたように、私が使用する一時テーブルがデータをロギングシステムとして格納することです。
これは、同じ時間間隔の作業ユニットに対して、任意の値 of FormIdNbを含めることができることを意味します。
例:1行FormIdNb = 2、1行FormIdNb = 3および1行FormIdNb = 4。
私の質問は:
無関係な値を取り除くリクエストを行う方法は?
より正確には:
作業ユニットが[〜#〜] active [〜#〜]であったが、[〜#〜] idle [〜#〜]でもあった場合および/または[〜#〜]非アクティブ[〜#〜]一定の間隔で、この作業ユニットを[〜#〜]アイドル[〜#]から「削除」する方法〜]および[〜#〜]非アクティブ[〜#〜]カウントし、時間間隔ごとにFormIdNbの最大値のみを保持しますか?
Scott Hodginに同意します。基本的に、FormIdNbではなくMAX(FormIdNb)を検討し、MAXの結果がより大きいか、等しいか、または等しいかに基づいて結果をカウントします。 3未満。
スコットが示唆しているように、相関サブクエリを結合条件に追加することは1つの方法です。
もう1つは、派生テーブルを使用して、最初に最大FormIdNb per NumCavalierおよび範囲を取得することです。
SELECT
t.StartTime,
d.NumCavalier,
MaxFormIdNb = MAX(d.FormIdNb)
FROM
time_cte AS t
LEFT OUTER JOIN #tmp_DailyMissions AS d
ON d.DateHeure >= t.StartTime
AND d.DateHeure < t.EndTime
GROUP BY
t.StartTime,
d.NumCavalier
そして、その時だけカウントを取得します。これはクエリ全体です:
WITH time_cte(StartTime, EndTime) AS
(
SELECT
StartTime = @starttime,
EndTime = DATEADD(mi, 15, @starttime)
UNION ALL
SELECT
EndTime,
DATEADD(mi, 15, EndTime)
FROM
time_cte
WHERE
EndTime < @EndTime
)
SELECT
StartTime,
ActiveUnitCount = COUNT(CASE WHEN MaxFormIdNb > 3 THEN d.NumCavalier END),
IdleUnitCount = COUNT(CASE WHEN MaxFormIdNb = 3 THEN d.NumCavalier END),
InactiveUnitCount = COUNT(CASE WHEN MaxFormIdNb < 3 THEN d.NumCavalier END)
FROM
(
SELECT
t.StartTime,
d.NumCavalier,
MaxFormIdNb = MAX(d.FormIdNb)
FROM
time_cte AS t
LEFT OUTER JOIN #tmp_DailyMissions AS d
ON d.DateHeure >= t.StartTime
AND d.DateHeure < t.EndTime
GROUP BY
t.StartTime,
d.NumCavalier
) AS s
GROUP BY
t.StartTime
;
派生テーブルは個別のNumCavalierのみを生成するため、現在はCOUNT(...)であり、COUNT(DISTINCT ...)ではないことに注意してください。 =とにかく値。
おそらく、何かが足りないのですが、処理しているタイムスライスの各NumCavalierにmax(formidnb)が必要なようです。私はこれを完全に構文チェックしていませんが、セミコロンのすぐ上に以下を追加できると思います
AND d.FormIdNb =
(
select MAX(FormIdNb)
FROM #tmp_DailyMissions
WHERE NumCavalier = d.NumCavalier and
DateHeure >= t.StartTime
AND DateHeure < t.EndTime
)