Postgresql 9.0を使用しています。テーブルに次のフィールドがあります:id, name
。
id name
1 John
1 Mary
1 Mary
1 Mary
1 John
1 Mary
3 Paul
3 Paul
3 George
. .
. .
id
ごとに、最も多く出現する名前を選択します。どうやってやるの?
次のクエリを試してみましたが、機能しません。
select id, max(name)
from table
group by id;
これは簡単なことではありません。まず、IDと名前でグループ化し、行をカウントします。
_SELECT COUNT(*)
...
GROUP BY id, name
_
次に、すべてのIDの最大数を選択します。これを実現する1つの方法は、ウィンドウ関数を使用することです。 RANK()
関数:
_RANK() OVER (PARTITION BY id ORDER BY COUNT(*) DESC)
_
(グループ化が行われた後)結果のすべての行に番号を割り当て、それらを(行)を同じid
のパーティションに配置し、COUNT(*) DESC
で順序付けするため、すべての(パーティションof)id
、最大カウントの行にはランク1が割り当てられます。したがって、上記を派生テーブルに入れ、WHERE
条件を使用してこれらのみを保持する必要があります行:
_WHERE rnk = 1
_
最終的なクエリは次のようになります。
_SELECT
id, name, cnt
FROM
( SELECT id, name, COUNT(*) AS cnt,
RANK() OVER (PARTITION BY id ORDER BY COUNT(*) DESC) AS rnk
FROM tableX
GROUP BY id, name
) AS tg
WHERE
rnk = 1 ;
_
SQL-Fiddleでテスト済み
最初に同点(同じ最大数の2つ以上の名前)がある場合、これらすべてが返されることに注意してください。最終結果のIDごとに厳密に1行が必要な場合は、ROW_NUMBER()
の代わりにRANK()
を使用し、_ORDER BY
_句を変更して、関係は解決されます:
_ROW_NUMBER() OVER (PARTITION BY id ORDER BY COUNT(*) DESC, name ASC) AS rnk
_
テスト済み:SQL-Fiddle test-2。