web-dev-qa-db-ja.com

値がリセットされるまでの累積期間

--DROP TABLE Taco_Val;
CREATE TABLE Taco_Val
(
    ID          INT IDENTITY(1,1),
    AuditID     VARCHAR(5),
    CreditID    VARCHAR(10),
    TS          DATETIME,
    Val         BIT
);

INSERT INTO Taco_Val
VALUES
 ('a1', 1, '2018-08-09 19:24:39.823',   1),--> Started 
 ('ac', 1, '2018-08-09 20:53:07.273',   0),
 ('as', 1, '2018-08-09 21:04:40.670',   0),
 ('a9', 1, '2018-08-09 21:14:17.660',   1),--> Another Seq
 ('av', 1, '2018-08-09 21:38:56.910',   1),
 ('ad', 1, '2018-08-09 21:48:46.180',   1),
 ('an', 1, '2018-08-09 22:00:15.650',   0),
 ('a4', 1, '2018-08-09 22:08:26.517',   1),-->Another Seq
 ('a8', 1, '2018-08-09 22:16:16.253',   0),
 ('a3', 1, '2018-08-09 22:16:24.247',   1),-->Another Seq
 ('ai', 1, '2018-08-09 22:18:59.143',   1),
 ('a3', 1, '2018-08-09 22:42:48.780',   1),
 ('ao', 1, '2018-08-09 22:51:21.117',   1),
 ('am', 1, '2018-08-09 23:01:13.777',   0),
 ('ac', 1, '2018-08-09 23:07:13.237',   0),
 ('ab', 1, '2018-08-09 23:16:38.257',   0),
 ('ay', 1, '2018-08-10 15:12:02.473',   1),-->Another Seq
 ('ae', 1, '2018-08-10 15:20:54.263',   0);

-次の出力が必要です

AuditID CreditID    StartTS            Val  Duration
a1      1           2018-08-09 19:24    1   100
a9      1           2018-08-09 21:14    1   46
a4      1           2018-08-09 22:08    1   8
a3      1           2018-08-09 22:16    1   60
ay      1           2018-08-10 15:12    1   8

Val = '1'sの行から開始(Val =' 1'sが連続している場合は行を無視しますが、最後の連続的な '0'が終了するまでTSで経過した時間を分単位でカウントします)

Val = '1'の次の行から再び開始

これが明確であることを願っています

4
SATISD9X

これは通常、GROUPING AND WINDOWSソリューションと呼ばれます。

基本的に、いくつかのルールに従ってリセットポイントを設定し、次にリセットポイントを合計することでグループを設定し、最後に集計関数を使用して目的の値を取得します。

;WITH reset AS
(
SELECT AuditID, 
       CreditID, 
       TS, 
       Val,
       /* Next CASE returns 1 when:
             a) It is the first row of a partition
             b) Current Val=1 and previous = 0
          Otherwise it returns 0
       */
       CASE WHEN Val=1 AND COALESCE(LAG(Val) OVER (PARTITION BY CreditID ORDER BY CreditID, TS), 0) = 0
            THEN 1 ELSE 0 END AS Rst        
FROM   Taco_Val
)
  , [group] AS
    (
    SELECT AuditID, 
           CreditID, 
           TS, 
           Val,
           /* Next SUM generates a cumulative sum of reset points.
              That is a correlative number for each partition
           */ 
           SUM(Rst) OVER (PARTITION BY CreditID ORDER BY CreditID, TS) AS Grp
    FROM   reset
    )
    SELECT 
           /* Next select returns, of every group, AuditID corresponding to
              the row with the minimum TS
           */ 
           (SELECT AuditID FROM [group] WHERE CreditID = g.CreditID AND TS = MIN(g.TS)) AuditID, 
           CreditID,
           MIN(TS) as StartTS, 
           1 as Val,
           DATEDIFF(MINUTE, MIN(TS), MAX(TS)) as Duration
    FROM   [group] g
    GROUP BY CreditID, Grp;
GO
 AuditID | CreditID | StartTS |ヴァル期間
:--- :------- | :------------------ | -:| -------:
 a1 | 1 | 2018年9月8日19:24:39 | 1 | 100 
 a9 | 1 | 2018年9月8日21:14:17 | 1 | 46 
 a4 | 1 | 2018/09/08 22:08:26 | 1 | 8 
 a3 | 1 | 2018/09/08 22:16:24 | 1 | 60 
 ay | 1 | 2018年10月8日15:12:02 | 1 | 8 

db <> fiddle ---(ここ

前のフィドルで、すべてのCTEの簡単な説明が見つかります。

6
McNets