アクティビティで数分だけ返す
最短
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;