グループ化された結果の各グループの上位n件のレコードを取得する [重複] 質問する

グループ化された結果の各グループの上位n件のレコードを取得する [重複] 質問する

以下は可能な限り最も単純な例ですが、どのソリューションでも、必要な n 個のトップ結果の数に応じて拡張できるはずです。

以下のような、人、グループ、年齢の列がある表があったら、どのようにしますか?各グループから最年長の 2 人を取得しますか?(グループ内で同点の場合は、それ以上の結果は表示されませんが、最初の 2 つがアルファベット順に表示されます)

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

望ましい結果セット:

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

注記:この質問は前回の質問に基づいています。グループ化されたSQL結果の各グループの最大値を持つレコードを取得します。- 各グループから 1 つの最上位行を取得するため、@Bohemian から MySQL 固有の優れた回答を受け取りました。

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

これを基に構築できれば良いのですが、方法がわかりません。

ベストアンサー1

これを行う方法の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;

見るデモ

おすすめ記事