「SQL Server - 相関副問い合わせ(相関サブクエリ)」の版間の差分

📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

 
27行目: 27行目:
#* サブクエリの結果を使用して、その行を最終結果に含めるかどうかが判断される。
#* サブクエリの結果を使用して、その行を最終結果に含めるかどうかが判断される。
# このプロセスが外部クエリの全てのレコードに対して繰り返される。
# このプロセスが外部クエリの全てのレコードに対して繰り返される。
<br>
==== WHERE句を使用する場合 ====
# 外部クエリがemployeesテーブルから最初の従業員レコードを取得する。
# その従業員のdepartmentカラムを使用して、サブクエリがその部門の平均給与を計算する。
# 従業員のsalaryカラムと計算された平均給与を比較する。
# 条件を満たせば結果セットに含める。
# 次の従業員レコードに移動して、2〜4を繰り返す。
<br>
<center>
{| class="wikitable" | style="background-color:#fefefe;"
|+ employeesテーブル
! style="background-color:#00ffff;" | employee_id
! style="background-color:#00ffff;" | employee_name
! style="background-color:#00ffff;" | salary
! style="background-color:#00ffff;" | department
! style="background-color:#00ffff;" | hire_date
|-
| 1 || 山田太郎 || 450,000 || 営業部 || 2020-04-01
|-
| 2 || 鈴木一郎 || 380,000 || 営業部 || 2021-04-01
|-
| 3 || 佐藤花子 || 370,000 || 経理部 || 2019-04-01
|-
| 4 || 田中次郎 || 420,000 || 営業部 || 2018-04-01
|-
| 5 || 高橋美咲 || 340,000 || 経理部 || 2022-04-01
|-
| 6 || 伊藤健一 || 390,000 || 人事部 || 2020-04-01
|-
| 7 || 渡辺直美 || 360,000 || 人事部 || 2021-04-01
|-
| 8 || 小林正和 || 430,000 || 営業部 || 2019-04-01
|-
| 9 || 加藤裕子 || 350,000 || 経理部 || 2022-04-01
|-
| 10 || 山本和夫 || 400,000 || 人事部 || 2018-04-01
|}
</center>
<br>
<br>
  <syntaxhighlight lang="sql">
  <syntaxhighlight lang="sql">
37行目: 75行目:
  );
  );
  </syntaxhighlight>
  </syntaxhighlight>
<br>
# 外部クエリがemployeesテーブルから最初の従業員レコードを取得する。
# その従業員のdepartmentカラムを使用して、サブクエリがその部門の平均給与を計算する。
# 従業員のsalaryカラムと計算された平均給与を比較する。
# 条件を満たせば結果セットに含める。
# 次の従業員レコードに移動して、2〜4を繰り返す。
<br>
<br>
このような動作特性から、以下に示すことがわかる。<br>
このような動作特性から、以下に示すことがわかる。<br>
48行目: 80行目:
* データ量が多い場合、パフォーマンスへの影響を考慮する必要がある。
* データ量が多い場合、パフォーマンスへの影響を考慮する必要がある。
* インデックスの適切な設定が重要になる。
* インデックスの適切な設定が重要になる。
<br>
====  グループ化する場合 ====
グループ化する場合は、JOINを使用する必要がある。<br>
<br>
<syntaxhighlight lang="sql">
SELECT e1.employee_name, e1.salary
FROM employees e1
JOIN (
    SELECT department, AVG(salary) as dept_avg
    FROM employees
    GROUP BY department
) e2 ON e1.department = e2.department
WHERE e1.salary > e2.dept_avg;
</syntaxhighlight>
<br>
このクエリの特徴を以下に示す。<br>
これは、大量のデータを処理する場合に有効である。<br>
* 相関サブクエリと比べて効率的である。
*: 部門ごとの平均計算は1回のみ
*: インデックスを効果的に使用可能
* 可読性が高い。
* 拡張性が高い。 (他の条件や計算を追加しやすい)
<br>
<syntaxhighlight lang="sql">
-- 内部クエリ (サブクエリ) の部分
-- 部門ごとの平均給与を計算する
SELECT department, AVG(salary) as dept_avg
FROM employees
GROUP BY department
-- 結果
department  | dept_avg
------------+---------
営業部      | 400,000
経理部      | 350,000
人事部      | 380,000
</syntaxhighlight>
<br>
<syntaxhighlight lang="sql">
-- JOINの部分
-- 元の従業員テーブル (e1) と、部門ごとの平均給与 (e2) を結合
-- 各従業員のレコードに、その従業員の所属部門の平均給与が付加される
FROM employees e1
JOIN (
    -- ...略
) e2 ON e1.department = e2.department
-- 結合後のイメージ
e1.name  | e1.salary | e1.department | e2.dept_avg
---------+-----------+---------------+-----------
山田太郎  | 450,000  | 営業部        | 400,000
鈴木一郎  | 380,000  | 営業部        | 400,000
佐藤花子  | 370,000  | 経理部        | 350,000
</syntaxhighlight>
<br>
<syntaxhighlight lang="sql">
-- WHERE句の部分
-- 結合後のデータから、給与が部門平均を上回る従業員のみを抽出する
WHERE e1.salary > e2.dept_avg
-- 最終結果
name    | salary
---------+---------
山田太郎  | 450,000
佐藤花子  | 370,000
</syntaxhighlight>
<br><br>
<br><br>