1. ホーム
  2. mysql

[解決済み] グループ化された結果の各グループの上位nレコードを取得する

2022-04-22 05:20:30

質問

以下は最も単純な例であるが、どのようなソリューションでも、必要な数のn個のトップ結果を得るために拡張できるはずである。

下のような表があり、person、group、ageの列がある場合、どのようにするのですか? 各グループの最年長者2人を取得する? (グループ内の同順位では結果が増えないはずですが、アルファベット順で最初の2つを与えてください)

+--------+-------+-----+
| 人物|グループ|年齢
+--------+-------+-----+
| ボブ|1|32|です。
| ジル|1|34
| ショーン|1|42
| ジェイク|2|29||。
| ポール|2|36
| ローラ|2|39|。
+--------+-------+-----+

希望する結果セット

+--------+-------+-----+
| ショーン|1|42||。
| ジル|1|34||。
| ローラ|2|39|。
| ポール|2|36
+--------+-------+-----+


NOTE この質問は、以前の質問を基にしたものです。 グループ化されたSQLの結果、各グループの最大値を持つレコードを取得する - は、各グループから単一の先頭行を取得するためのもので、@Bohemian から MySQL に特化したすばらしい回答が得られました。

select * 
from (select * from mytable order by `Group`, Age desc, Person) x
group by `Group`

これをベースに構築できればと思いますが、方法はわかりません。

どのように解決するのですか?

ここでは、1つの方法として UNION ALL (参照 SQLデモ ). これは2つのグループで動作しますが、2つ以上のグループがある場合は group の数を増やし、それぞれのクエリを追加します。 group :

(
  select *
  from mytable 
  where `group` = 1
  order by age desc
  LIMIT 2
)
UNION ALL
(
  select *
  from mytable 
  where `group` = 2
  order by age desc
  LIMIT 2
)

様々な方法がありますので、こちらの記事を参考に、状況に応じた最適なルートを判断してください。

http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

編集する

これは、各レコードの行番号を生成するもので、あなたにも使えるかもしれません。上のリンクの例では、行番号が2以下のレコードのみを返します。

select person, `group`, age
from 
(
   select person, `group`, age,
      (@num:=if(@group = `group`, @num +1, if(@group := `group`, 1, 1))) row_number 
  from test t
  CROSS JOIN (select @num:=0, @group:=null) c
  order by `Group`, Age desc, person
) as x 
where x.row_number <= 2;

参照 デモ