アクティビティで数分だけ返す
最短
SELECT DISTINCT
date_trunc('minute', "when") AS minute
, count(*) OVER (ORDER BY date_trunc('minute', "when")) AS running_ct
FROM mytable
ORDER BY 1;
date_trunc()を使用します 、必要なものを正確に返します。
idを含めないでください GROUP BY を実行したいので、クエリで 分のスライス。
count() 通常、単純な集計関数として使用されます。 OVERを追加する 句はそれをウィンドウ関数にします。 PARTITION BYを省略します ウィンドウ定義で-すべての行の実行カウントが必要です 。デフォルトでは、 ORDER BY で定義されているように、現在の行の最初の行から最後のピアまでカウントされます。 。マニュアル:
デフォルトのフレーミングオプションは
RANGEUNBOUNDED PRECEDINGです。 、これはUNBOUNDEDPRECEDINGとCURRENTROWの間の範囲と同じです。 。ORDER BYを使用 、これにより、フレームは、パーティションの開始から現在の行の最後のORDER BYまでのすべての行に設定されます。 ピア。
そして、それはたまたま正確に 必要なもの。
count(*)を使用する count(id)ではなく 。それはあなたの質問(「行数」)によりよく適合します。通常、わずかに速い count(id)より 。そして、 id NOT NULLです 、質問で指定されていないため、 count(id) 間違っている 、厳密に言えば、NULL値は count(id)ではカウントされないためです。 。
GROUP BYはできません 同じクエリレベルでの分のスライス。集計関数は前に適用されます ウィンドウ関数、ウィンドウ関数 count(*) この方法では、1分あたり1行しか表示されません。
ただし、 SELECT DISTINCT 、 DISTINCT 後に適用されます ウィンドウ関数。
ORDER BY 1 ORDER BY date_trunc('minute'、 "when")の省略形です。 ここ。1 SELECTの最初の式への位置参照参照です リスト。
to_char()を使用する 結果をフォーマットする必要がある場合。いいね:
SELECT DISTINCT
to_char(date_trunc('minute', "when"), 'DD.MM.YYYY HH24:MI') AS minute
, count(*) OVER (ORDER BY date_trunc('minute', "when")) AS running_ct
FROM mytable
ORDER BY date_trunc('minute', "when");
最速
SELECT minute, sum(minute_ct) OVER (ORDER BY minute) AS running_ct
FROM (
SELECT date_trunc('minute', "when") AS minute
, count(*) AS minute_ct
FROM tbl
GROUP BY 1
) sub
ORDER BY 1;
上記とよく似ていますが:
サブクエリを使用して、1分あたりの行数を集計およびカウントします。このようにして、 DISTINCTなしで1分あたり1行を取得します 外側のSELECT 。
sum()を使用する サブクエリからのカウントを合計するためのウィンドウ集計関数として。
これは、1分あたりの行数が多いため、大幅に高速であることがわかりました。
アクティビティのない分を含める
最短
@GabiMeはコメントで、すべてのeone行を取得する方法を尋ねました 分コード> イベントが発生しなかった(ベーステーブルに行がない)時間を含む時間枠内:
SELECT DISTINCT
minute, count(c.minute) OVER (ORDER BY minute) AS running_ct
FROM (
SELECT generate_series(date_trunc('minute', min("when"))
, max("when")
, interval '1 min')
FROM tbl
) m(minute)
LEFT JOIN (SELECT date_trunc('minute', "when") FROM tbl) c(minute) USING (minute)
ORDER BY 1;
generate_series()を使用して、最初のイベントと最後のイベントの間の時間枠で1分ごとに行を生成します -ここでは、サブクエリからの集計値に直接基づいています。
LEFT JOIN 分とカウントに切り捨てられたすべてのタイムスタンプに。 NULL 値(行が存在しない場合)は実行カウントに追加されません。
最速
CTEの場合:
WITH cte AS (
SELECT date_trunc('minute', "when") AS minute, count(*) AS minute_ct
FROM tbl
GROUP BY 1
)
SELECT m.minute
, COALESCE(sum(cte.minute_ct) OVER (ORDER BY m.minute), 0) AS running_ct
FROM (
SELECT generate_series(min(minute), max(minute), interval '1 min')
FROM cte
) m(minute)
LEFT JOIN cte USING (minute)
ORDER BY 1;
繰り返しになりますが、最初のステップで1分あたりの行数を集計してカウントします。これにより、後の DISTINCTが不要になります。 。
count()とは異なります 、 sum() NULLを返すことができます 。デフォルトは0 COALESCEを使用 。
多くの行と"when"のインデックス サブクエリを含むこのバージョンは、Postgres 9.1-9.4でテストしたいくつかのバリアントの中で最速でした:
SELECT m.minute
, COALESCE(sum(c.minute_ct) OVER (ORDER BY m.minute), 0) AS running_ct
FROM (
SELECT generate_series(date_trunc('minute', min("when"))
, max("when")
, interval '1 min')
FROM tbl
) m(minute)
LEFT JOIN (
SELECT date_trunc('minute', "when") AS minute
, count(*) AS minute_ct
FROM tbl
GROUP BY 1
) c USING (minute)
ORDER BY 1;