質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Q&A

解決済

1回答

715閲覧

最大値の集計を取得したい

Fur0

総合スコア48

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

0グッド

0クリップ

投稿2021/04/26 21:26

実現したいこと

横持ちのデータに対して、最大値の集計値TOP3を取得したいです。

名前 要素① 要路② 要素③ 要素④
太郎  40   30   20    10
次郎 30 20 10 40
三郎 40 30 20 10
四郎 40 30 20 10
五郎 30 20 10 40
六郎 10 40 30 20

例えば、上記の場合は、
・太郎さんにとって最も得点の高い要素は①
・次郎さんにとって最も得点の高い要素は④
・三郎さんにとって最も得点の高い要素は①
・四郎さんにとって最も得点の高い要素は①
・五郎さんにとって最も得点の高い要素は④
・六郎さんにとって最も得点の高い要素は②
となるため、「要素① 3件」「要素④ 2件」「要素② 1件」と出力したいです。

発生している問題

group by句、count関数を使用するイメージは湧きましたが、どのように取得すれば良いか、具体的なSQLが書けません。
要素名と件数は別々に求める方法でもOKですので、ご教示ください。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

複数のカラムを対象に最大値を求めるには、greatest()を用います。
各々の要素と最大値を比較して、一致していればその要素が最大値です。
※実行可能な様に、from句は質問のデータを展開しています。
尚、同点があると各々の要素でカウントされます。

SQL

1select sum(case when 要素① = greatest(要素①,要素②,要素③,要素④) then 1 else 0 end) as 要素① 2 , sum(case when 要素② = greatest(要素①,要素②,要素③,要素④) then 1 else 0 end) as 要素② 3 , sum(case when 要素③ = greatest(要素①,要素②,要素③,要素④) then 1 else 0 end) as 要素③ 4 , sum(case when 要素④ = greatest(要素①,要素②,要素③,要素④) then 1 else 0 end) as 要素④ 5from (values 6 ('太郎',40,30,20,10) 7 ,('次郎',30,20,10,40) 8 ,('三郎',40,30,20,10) 9 ,('四郎',40,30,20,10) 10 ,('五郎',30,20,10,40) 11 ,('六郎',10,40,30,20) 12 ) as w(名前,要素①,要素②,要素③,要素④)

追記

TOP3に対応。
集計したものをunnest()を使用して、横を縦に変換(配列を行集合に展開)し、limitします。

SQL

1with tbl as ( 2 select * 3 from (values 4 ('太郎',40,30,20,10) 5 ,('次郎',30,20,10,40) 6 ,('三郎',40,30,20,10) 7 ,('四郎',40,30,20,10) 8 ,('五郎',30,20,10,40) 9 ,('六郎',10,40,30,20) 10 ) as w(名前,要素①,要素②,要素③,要素④) 11) 12select 要素No, 要素件数 13from ( 14 select sum(case when 要素① = greatest(要素①,要素②,要素③,要素④) then 1 else 0 end) as 要素① 15 , sum(case when 要素② = greatest(要素①,要素②,要素③,要素④) then 1 else 0 end) as 要素② 16 , sum(case when 要素③ = greatest(要素①,要素②,要素③,要素④) then 1 else 0 end) as 要素③ 17 , sum(case when 要素④ = greatest(要素①,要素②,要素③,要素④) then 1 else 0 end) as 要素④ 18 from tbl 19 ) t 20 , unnest(array[要素①,要素②,要素③,要素④]::integer[]) with ordinality as u(要素件数, 要素No) 21order by 要素件数 desc limit 3

元々は正規化されていない状態が、集計し辛い状況を作っているので、unnestを使用して一旦正規化し
て集計した場合は以下。

SQL

1with tbl as ( 2 select * 3 from (values 4 ('太郎',40,30,20,10) 5 ,('次郎',30,20,10,40) 6 ,('三郎',40,30,20,10) 7 ,('四郎',40,30,20,10) 8 ,('五郎',30,20,10,40) 9 ,('六郎',10,40,30,20) 10 ) as w(名前,要素①,要素②,要素③,要素④) 11) 12select 要素NO, count(*) as 件数 13from ( 14 select *, max(要素) over(partition by 名前)=要素 as 最大要素 15 from ( 16 select 名前, 要素No, 要素 17 from tbl, unnest(array[要素①,要素②,要素③,要素④]::integer[]) with ordinality as u(要素, 要素No) 18 ) nomalize 19) pick_max 20where 最大要素 21group by 要素No 22order by count(*) desc limit 3

正規化された状態のテーブルだった場合で記述すると、以下の様にシンプルになります。

SQL

1select 要素NO, count(*) as 件数 2from ( 3 select *, max(要素) over(partition by 名前)=要素 as 最大要素 4 from tbl 5) pick_max 6where 最大要素 7group by 要素No 8order by count(*) desc limit 3

投稿2021/04/27 00:24

編集2021/04/27 01:07
sazi

総合スコア25206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2021/04/27 01:05 編集

> 最大値の集計値TOP3 を見落としていましたので、追記しました。
Fur0

2021/04/27 12:54

返信が遅くなり申し訳ありません。 greatest関数というものがあるのですね。 ご回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問