標準の GROUP BY クエリは、ほとんどの方法で取得できます。
SELECT
user_id,
type_of_place,
avg(money_earned) AS avg,
stddev(money_earned) AS stddev
FROM
earnings -- I'm not sure what your data table is called...
GROUP BY
user_id,
type_of_place
これにより、列top5_places
とmode
列が残ります。これらは両方とも集約ですが、標準の PostgreSQL インストールで定義されているものではありません。幸いなことに、それらを追加できます。
mode
集計関数 を定義する方法について説明しているページは次のとおりです: http://wiki.postgresql.org/wiki/Aggregate_Mode
何らかのタイムスタンプであるmode
と仮定して集計関数を作成したら、選択リストに追加する式は次のようになります。time
SELECT
...
mode(extract(hour FROM time)) AS mode -- Add this expression
FROM
...
お金による注文を想定
の場合top5_places
、いくつかのアプローチがありますが、最も速いのは、おそらく PostgreSQL の組み込みarray_agg
関数を使用して、最初の 5 つの要素を取得することです。
SELECT
...
(array_agg(place ORDER BY money_earned DESC))[1:5] AS top5_places -- Add this expression
FROM
...
top5
1 つの代替方法は、同じ機能を実行する(たとえば) という別の集約を定義することです。ユーザー/場所の組み合わせごとに異なる場所が多数ある場合、最初の 5 つを超えると蓄積が停止する可能性があるため、これはより効率的です。一方、上記の式は通常、すべての場所の完全な配列を構築し、最初の場所に切り詰めます。 5.
これは、ユーザーとタイプの組み合わせごとに場所に固有の収益エントリがあることを前提としています。 場所が複数回発生する可能性があり、sum(money_earned)
場所ごとに並べ替えたい場合は、以下の例のようにサブクエリを使用する必要があります...
カウント順
わかりましたので、場所は発生頻度で並べる必要があります。いくつかのサブクエリを使用する簡単な方法を次に示します。これを式として上記のクエリの select-clause に追加します。
(SELECT
(array_agg(place ORDER BY cnt DESC))[1:5]
FROM
(SELECT place, count(*) FROM earnings AS t2
WHERE t2.user_id = earnings.user_id AND t2.type_of_place = earnings.type_of_place
GROUP BY place) AS s (place, cnt)
) AS top5_places
呼び出された内側のサブクエリは、そのユーザー/タイプの組み合わせs
のそれぞれのテーブルplace
と、それが発生した回数 (私が呼び出したものcnt
) に評価されます。これらはarray_agg
、そのカウントの降順で供給されます。
もっときちんとした (そしておそらくもっと効率的な) 書き方があるのではないかと思います。そうでない場合は、可能であれば、この複雑な式を関数または集計に移動することをお勧めします...
時間ごとの場所のヒストグラム
同様の式を使用すると、時間順に並べられたカウントの配列が返されます。
(SELECT
array_agg(cnt ORDER BY hour DESC)
FROM
(SELECT extract(hour FROM time), count(*) FROM earnings AS t2
WHERE t2.user_id = earnings.user_id AND t2.type_of_place = earnings.type_of_place
GROUP BY 1) AS s (hour, cnt)
) AS hourly_histogram
(それを元のクエリの select-clause に追加します。)