コマンド道場
相関副問い合わせ難易度 ★★★★

部署の平均を上回る社員

在籍中の社員のうち、給与が「自分が所属する部署の平均給与」を上回る人を取り出してください。平均を求めるときも退職者は含めません。列は「部署名, 名前, 給与」の順、部署番号(busho_id)の小さい順に並べ、同じ部署の中では給与の高い順にしてください。部署に所属していない社員は対象外です。

主要 7 製品で通用 そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite / SQL Server / Oracle Database / IBM Db2

製品ごとの対応表(実測)を見る

  • 内側の副問い合わせが外側の列を参照していると、外側の 1 行ごとに評価されます。これを相関副問い合わせと呼びます。
  • 同じことはウィンドウ関数(avg(...) OVER (PARTITION BY ...))でも書けます。行数が多いときはそちらの方が速いことがあります。
● 起動中…

この問題で使えるテーブル(名前をタップすると入力できます)

7

NULL
🔑int不可
text不可
int
データを見る(先頭 5 行)
busho_idbusho_nameparent_busho_id
1経営NULL
2開発1
3営業1
4管理1
5基盤2

18

NULL
🔑int不可
text不可
int
int
numeric(10,0)不可
date不可
date
データを見る(先頭 5 行)
shain_idnamebusho_idjoushi_idsalaryhired_ontaishoku_on
1鈴木1NULL9800002014-04-01NULL
2佐藤217200002016-10-01NULL
3田中225200002019-04-01NULL
4中村225300002020-04-01NULL
5小林224450502024-04-01NULL

解説

結論

副問い合わせの中から外側の行の列を参照すると、比較の基準が行ごとに変わります。これを相関副問い合わせと呼びます。

なぜ

前問(全社平均)の副問い合わせは、外側の行が何であっても同じ 1 つの値を返しました。今回は括弧の中に s2.busho_id = s.busho_id という条件があるため、評価する社員が変わると副問い合わせの結果も変わります。「行ごとに別の値を計算する」という発想がここで必要になります。

★表の別名が必須になる理由: 内側でも外側でも同じ shain 表を使うため、別名を付けないと busho_id がどちらの表のものか区別できません。s と s2 のように分けることで、s.busho_id は外側の行、s2.busho_id は内側の行を指すことが明確になります。

★「上回る」を >= と書くとどうなるか: 在籍者が 1 人しかいない部署では、その人の給与がそのまま部署の平均になります。>= だと自分自身と等しいので必ず結果に現れます。このデータには在籍者が 1 人だけの部署があるので、> と >= のどちらで書いたかが結果に出ます。「平均より上」を求めるときは、この一人部署の扱いを意識してください。

⚠️ 相関副問い合わせは「行の数だけ副問い合わせが評価される」形になるため、件数が多い表では遅くなりがちです。実際にはデータベース側が結合に書き換えて処理することも多いのですが、遅い場合はウィンドウ関数(avg(salary) OVER (PARTITION BY busho_id))や、部署ごとの平均を求めた派生表との結合に書き換えると改善します。

よくある間違い

①相関の条件を書き忘れ、全体の平均と比べてしまう(エラーにならないので気づきにくい)。②内側と外側で条件がそろっていない。③別名を付けずに書いて、意図しない方の列を参照する。

根拠(一次情報)