sql >> データベース >  >> RDS >> PostgreSQL

行間の時間差の合計

    特別な難しさは、外側の時間枠までの期間を見逃さないことです。
    任意のidの次の行を想定します。 常に反対のステータスになります。
    列名を使用するts recordTimeの代わりに :

    WITH span AS (
       SELECT '2014-03-01 13:00'::timestamp AS s_from  -- start of time range
            , '2014-03-01 14:00'::timestamp AS s_to    -- end of time range
       )
    , cte AS (
       SELECT id, ts, status, s_to
            , lead(ts, 1, s_from) OVER w AS span_start
            , first_value(ts)     OVER w AS last_ts
       FROM   span s
       JOIN   tbl  t ON t.ts BETWEEN s.s_from AND s.s_to
       WINDOW w AS (PARTITION BY id ORDER BY ts DESC)
       )
    SELECT id, sum(time_disconnected)::text AS total_disconnected
    FROM  (
       SELECT id, ts - span_start AS time_disconnected
       FROM   cte
       WHERE  status = 'Connected'
    
       UNION  ALL  
       SELECT id, s_to - ts
       FROM   cte
       WHERE  status = 'Disconnected'
       AND    ts = last_ts
       ) sub
    GROUP  BY 1
    ORDER  BY 1;
    

    要求に応じて間隔を返します。
    選択した時間範囲にエントリがないIDは表示されません。さらにクエリを実行する必要があります。

    SQLフィドル。
    注:結果のtotal_disconnectedをキャストしました textへ タイプintervalであるため、フィドルで ひどい形式で表示されます。

    選択した時間枠に入力せずにIDを追加


    上記のクエリに追加します(最後のORDER BY 1の前) ):

    ...
    UNION  ALL
    SELECT id, total_disconnected
       FROM  (
       SELECT DISTINCT ON (id)
              t.id, t.status, (s.s_to - s.s_from)::text AS total_disconnected
       FROM   span     s
       JOIN   tbl      t ON t.ts < s.s_from  -- only from before time range
       LEFT   JOIN cte c USING (id)
       WHERE  c.id IS NULL         -- not represented in selected time frame
       ORDER  BY t.id, t.ts DESC   -- only the latest entry
       ) sub
    WHERE  status = 'Disconnected' -- only if disconnected
    ORDER  BY 1;
    

    SQLフィドル。

    現在、またはそれ以前にエントリのないIDのみ 選択した時間範囲は表示されません。



    1. PostgreSQLで複数の列の合計を計算する方法

    2. PHP 5の代替関数mysql_list_tables()は何ですか

    3. ルックアップテーブルはどのくらい重要ですか?

    4. mysqlでクライアントIPアドレスを取得します