次の(不自然な)監視データのテーブルがあるとします。
RowID DateStamp Success Error
----- ----------------- ------- -----------
1001 5/24/2019 11:23am 1 None
1004 5/24/2019 11:24am 1 None
1005 5/24/2019 11:25am 1 None
1009 5/24/2019 11:26am 0 SQL Timeout
1018 5/24/2019 11:27am 0 SQL Timeout
1019 5/24/2019 11:28am 1 None
1026 5/24/2019 11:29am 1 None
1035 5/24/2019 11:30am 0 Planned Maintenance
1100 5/24/2019 11:31am 0 Planned Maintenance
1111 5/24/2019 11:32am 1 None
同じステータスとエラーの行をグループ化したいのですが、行が順番に並んでいる場合のみ日付またはIDで(IDは正しく順序付けされますが、保証されていません)順次)、次のように:
Starting Ending Polls Success Error
----------------- ----------------- ----- ------- -----------
5/24/2019 11:23am 5/24/2019 11:25am 3 1 None
5/24/2019 11:26am 5/24/2019 11:27am 2 0 SQL Timeout
5/24/2019 11:28am 5/24/2019 11:29am 2 1 None
5/24/2019 11:30am 5/24/2019 11:31am 2 0 Planned Maintenance
5/24/2019 11:32am 5/24/2019 11:32am 1 1 None
シンプルな GROUP BY
が機能しません:
SELECT MIN(DateStamp) as Starting, MAX(DateStamp) as Ending,
Count(*) as Polls, Success, Error
FROM myTable
GROUP BY Success, Error
ORDER BY Starting
いつ発生したかに関係なく、すべての行が同じステータス/エラーに結合されるため、次のようになります。
Starting Ending Polls Success Error
----------------- ----------------- ----- ------- -----------
5/24/2019 11:23am 5/24/2019 11:32am 6 1 None
5/24/2019 11:26am 5/24/2019 11:27am 2 0 SQL Timeout
5/24/2019 11:30am 5/24/2019 11:31am 2 0 Planned Maintenance
SQL Server 2012でこれを行う簡単な方法はありますか?
アイランドを特定する別の方法は、LAG
分析関数とSUM()
ウィンドウ集約関数を使用することです。
WITH
sentinels AS
(
SELECT
DateStamp,
Success,
Error,
Grp = CASE
WHEN Success = LAG(Success) OVER (ORDER BY DateStamp ASC)
AND Error = LAG(Error ) OVER (ORDER BY DateStamp ASC)
THEN 0
ELSE 1
END
FROM
dbo.myTable
),
fullyMarked AS
(
SELECT
DateStamp,
Success,
Error,
Grp = SUM(Grp) OVER (ORDER BY DateStamp ASC ROWS UNBOUNDED PRECEDING)
FROM
sentinels
)
SELECT
Starting = MIN(DateStamp),
Ending = MAX(DateStamp),
Polls = COUNT(*),
Success,
Error
FROM
fullyMarked
GROUP BY
Success,
Error,
Grp
ORDER BY
Starting ASC
;
sentinels
CTEは、各アイランドの最初の行を1でマークし、他の行を0でマークします。
RowID DateStamp Success Error Grp
----- ----------------- ------- ------------------- ---
1001 5/24/2019 11:23am 1 None 1
1004 5/24/2019 11:24am 1 None 0
1005 5/24/2019 11:25am 1 None 0
1009 5/24/2019 11:26am 0 SQL Timeout 1
1018 5/24/2019 11:27am 0 SQL Timeout 0
1019 5/24/2019 11:28am 1 None 1
1026 5/24/2019 11:29am 1 None 0
1035 5/24/2019 11:30am 0 Planned Maintenance 1
1100 5/24/2019 11:31am 0 Planned Maintenance 0
1111 5/24/2019 11:32am 1 None 1
fullyMarked
CTEはsentinels
の出力を受け取り、Grp
列の現在までの合計を計算します。これにより、各アイランドに一意のIDを効果的に割り当てます。
RowID DateStamp Success Error Grp
----- ----------------- ------- ------------------- ---
1001 5/24/2019 11:23am 1 None 1 -- 1
1004 5/24/2019 11:24am 1 None 1 -- 1+0
1005 5/24/2019 11:25am 1 None 1 -- 1+0+0
1009 5/24/2019 11:26am 0 SQL Timeout 2 -- 1+0+0+1
1018 5/24/2019 11:27am 0 SQL Timeout 2 -- 1+0+0+1+0
1019 5/24/2019 11:28am 1 None 3 -- 1+0+0+1+0+1
1026 5/24/2019 11:29am 1 None 3 -- 1+0+0+1+0+1+0
1035 5/24/2019 11:30am 0 Planned Maintenance 4 -- 1+0+0+1+0+1+0+1
1100 5/24/2019 11:31am 0 Planned Maintenance 4 -- 1+0+0+1+0+1+0+1+0
1111 5/24/2019 11:32am 1 None 5 -- 1+0+0+1+0+1+0+1+0+1
最後のステップは、Success, Error, Grp
および必要に応じて他の列のデータを集計します。これにより、期待どおりの結果が得られます。
あなたはこれを使うことができます ライブデモ このソリューションを試すためのdb <> fiddle.uk。
これは、ROW_NUMBER()
を使用してグループを作成する1つの例です。
_;WITH CTE_GROUP AS (
SELECT
Success,
Error,
DateStamp,
ROW_NUMBER() OVER (PARTITION BY Success, Error ORDER BY DateStamp)
- ROW_NUMBER() OVER (ORDER BY DateStamp) as SuccesErrorDateStamp,
FROM dbo.myTable
)
SELECT MIN(DateStamp) as Starting, MAX(DateStamp) as Ending,
Count(*) as Polls, Success, Error
FROM CTE_GROUP
GROUP BY Success, Error,SuccesErrorDateStamp
ORDER BY Starting;
_
結果
_Starting Ending Polls Success Error
2019-05-24 11:23:00.0000000 2019-05-24 11:25:00.0000000 3 1 None
2019-05-24 11:26:00.0000000 2019-05-24 11:27:00.0000000 2 0 SQL Timeout
2019-05-24 11:28:00.0000000 2019-05-24 11:29:00.0000000 2 1 None
2019-05-24 11:30:00.0000000 2019-05-24 11:31:00.0000000 2 0 Planned Maintenance
2019-05-24 11:32:00.0000000 2019-05-24 11:32:00.0000000 1 1 None
_
ありがとう @ AndriyM 必要なのはROW_NUMBER()
列が1つだけであることを指摘してください