データベースを扱うとき、「複数のテーブルを結合して最終的に件数を出したい」 という場面はよくあります。
例えば次のような構造を考えてみましょう。
最終的には「拠点+組織ごとのユーザー数」を1本のSQLで取得したいわけです。
まずは単純に分けて考えるとこうなります。
SELECT DISTINCT
B.組織コード,
A.拠点コード,
A.住所
FROM Aテーブル A
LEFT JOIN Bテーブル B
ON B.拠点コード = A.拠点コード;
SELECT
組織コード,
COUNT(ユーザーID) AS 件数
FROM Cテーブル
GROUP BY 組織コード;
実際には JOINを重ねてGROUP BYするだけ で、1つにまとめられます。
SELECT
B.組織コード,
A.拠点コード,
A.住所,
COALESCE(COUNT(C.ユーザーID), 0) AS 件数
FROM Aテーブル A
LEFT JOIN Bテーブル B
ON B.拠点コード = A.拠点コード
LEFT JOIN Cテーブル C
ON C.組織コード = B.組織コード
GROUP BY
B.組織コード,
A.拠点コード,
A.住所;
SELECT
B.組織コード,
A.拠点コード,
A.住所,
COUNT(C.ユーザーID) AS 件数
FROM Aテーブル A
INNER JOIN Bテーブル B
ON B.拠点コード = A.拠点コード
INNER JOIN Cテーブル C
ON C.組織コード = B.組織コード
GROUP BY
B.組織コード,
A.拠点コード,
A.住所;
LEFT JOIN + COALESCE() → 件数が無くても0で表示INNER JOIN → 件数がある組織だけ抽出そんな時に便利なのが WITH句(Common Table Expression, CTE) です。
サブクエリに名前をつけて、処理を段階的に整理できます。
USE SampleDB;
WITH q1 AS (
SELECT DISTINCT
a.Unit_Code, -- 組織コード
p.Location_Code, -- 拠点コード
p.Location_Name -- 拠点名
FROM A_Location_Master p
LEFT JOIN B_Unit_Location a
ON a.Location_Code = p.Location_Code
),
q2 AS (
SELECT
o.Unit_Code,
COUNT(o.User_Id) AS EmployeeCount
FROM C_Employee_Unit o
GROUP BY o.Unit_Code
)
SELECT
q1.Unit_Code,
q1.Location_Name,
q2.EmployeeCount
FROM q1
INNER JOIN q2
ON q2.Unit_Code = q1.Unit_Code;
👉 このように 処理を2段階に分けて名前をつける ことで、SQLの流れがはっきりします。
COALESCEを使えばNULLを0として扱えるWITHを使うとクエリの見通しが良くなり、ナレッジとして共有する時にも分かりやすいSQLは「動けばOK」ではなく、「読みやすさ・保守しやすさ」も大事です。
特に社内ナレッジとして残す場合、WITHで分割して説明しやすくするのがおすすめです。