web-dev-qa-db-ja.com

Postgres:group byの結果を列名として使用

データベースにメッセージテーブルがあり、送信者IDとメッセージタイプが含まれています(もちろん、この質問には関係のない列がさらに多くあります)。ユーザーが送信した各タイプのメッセージの数を数えるクエリを作成しようとしています。

例えば次の表がある場合:

 --------------------------- 
 id | user_id | message_type 
 --------------------------- 
 1 | 1 |プライベート
 2 | 1 | public 
 3 | 1 |民間
 -  -  -  -  -  -  -  -  -  -  -  -  - -

次に、以下を取得します。

 --------------------- 
 id |プライベート| public 
 --------------------- 
 1 | 2 | 1 
 --------------------- 

したがって、実際にはmessage_typeとuser_idでグループ化したいのですが、ユーザーごとに複数の行を生成するのではなく、message_typeごとに1つずつ、複数の列を作成したいと思います。

クエリでメッセージタイプをハードコーディングせずにこれを実現できますか?

6
Tiddo

列に変換する値の数が限られている場合は、CASE式を使用した集計関数を使用して簡単に実装できます。

_select user_id,
  sum(case when message_type = 'private' then 1 else 0 end) private,
  sum(case when message_type = 'public' then 1 else 0 end) public
from yourtable
group by user_id
_

参照 SQL Fiddleデモあり

PostgreSQLには、_ tablefunc モジュールをインストールすることで使用できるcrosstab()を使用する機能があります。これにより、行から列への同様のデータ変換が実行されます。クエリの動的バージョンを作成することは簡単なプロセスではありません。これが StackOverflowの動的クロス集計 の優れたソリューションです。

9
Taryn

PostgreSQLは、PIVOTを直接サポートしていません。PIVOTは、通常、他のプラットフォームでこのような目的で使用されるキーワードです。 (tablefunc モジュールには、doesのクロス集計関数がいくつかあります。

crosstab()関数を使用 、(優れたStackOverflow回答)