データベースのタイム スライスが必要なタイム スライスよりも大きい場合に、データからタイム スライスをクエリする方法。最終結果は積み上げ棒グラフの描画に使用されます。
サンプルデータ:
START_TS (int)| END_TS (int) | DATA (int) | GROUP
-----------------------------------
0 | 179 | 2000 | G1
180 | 499 | 1000 | G2
500 | 699 | 1000 | G1
845 ...
タイムスライスを 100 の「単位」として使用した出力が必要でした。End_ts は出力には必要ありませんが、計算を理解するのに役立ちます。
START_TS | END_TS | DATA (equation = amount in that time slice) | GROUP
-------------------------------------------------------
0 | 99 | (2000 / 180) * 100 = 1111 | G1
100 | 199 | (2000 / 180) * 80 = 889 | G1
100 | 199 | (1000 / 320) * 20 = 63 | G2
200 | 299 | (1000 / 320) * 100 = 313 | G2
300 | 399 | (1000 / 320) * 100 = 313 | G2
400 | 499 | (1000 / 320) * 100 = 313 | G2
ここから時系列を出すとこんな感じ。
SELECT (startts/100)*100, ...
FROM TABLE
FULL JOIN
( SELECT startts from generate_series(0,700,100) startts ) s1
USING (startts)
GROUP BY startts/100
したがって、このようなものになります(グループ化なし)
STARTTS | ENDTS | DATA | GROUP
0 | 179 | 2000 | G1
100 |
180 | 499 | 1000 | G2
200 |
300 |
400 |
500 | 699 | 1000 | G1
600 |
700
しかし、DATA を 2 つ以上の生成された行 (タイム スライス行) に分割して、タイム スライスで計算するにはどうすればよいでしょうか。
** これは基本的に機能しますが、大きなデータセットでは実際には機能しません。1-100M 行のような行。
これを実行するためのクエリと、タイム スライスが重複しない値を集計するための追加のクエリを次に示します。
SELECT (start_ts/100)*100 as start_ts, sum(part) as data, cgroup
FROM (
SELECT *, ( data * (overlap_end-overlap_start + 1 ) / ( end_ts - tts + 1 ) ) as part
FROM
(
SELECT (case when s1.start_ts > t.start_ts then s1.start_ts else t.start_ts end) as overlap_start,
(case when s1.start_ts+100 < t.end_ts then s1.start_ts+100-1 else t.end_ts end) as overlap_end,
t.start_ts as tts, s1.start_ts as start_ts, t.end_ts, cgroup, data
FROM (SELECT start_ts from generate_series(0,800,100) start_ts ) s1
LEFT OUTER JOIN test t on t.start_ts < s1.start_ts+100 and t.end_ts >= s1.start_ts
) t
) t2
GROUP BY start_ts/100, cgroup