SQL Server: LEFT JOINで全件結合&TOP 1句で最初のレコードのみ抽出!応用例と詳細解説
SQL Server で LEFT JOIN を使って TOP 1 レコードを取得する方法
SQL Server で複数のテーブルを結合する場合、JOIN 操作がよく使用されます。JOIN には様々な種類があり、それぞれ異なる方法でレコードを結合します。
本記事では、LEFT JOIN と TOP 1 句を組み合わせて、左側テーブルのすべてのレコードと、右側テーブルに一致するレコードがあれば 1 件のみ を取得する方法について解説します。
LEFT JOIN は、左側テーブルのすべてのレコードを結合結果に含め、右側テーブルに一致するレコードがあれば右側テーブルの対応する列も結合します。一致するレコードがない場合は、右側テーブルの列は NULL 値となります。
TOP 1 句は、SELECT ステートメントの結果セットから最初の 1 件のみを取得します。
LEFT JOIN と TOP 1 句を組み合わせる
例
次の例では、Customers
テーブルと Orders
テーブルを結合し、各顧客の最新の注文を取得します。
SELECT
c.CustomerID,
c.CompanyName,
o.OrderID,
o.OrderDate
FROM Customers c
LEFT JOIN Orders o ON c.CustomerID = o.CustomerID
ORDER BY o.OrderDate DESC
TOP 1;
このクエリは、以下の結果を返します。
CustomerID | CompanyName | OrderID | OrderDate
-----------+------------+---------+------------
1 | ABC Corp | 10243 | 2024-05-19
このクエリでは、Customers
テーブルのすべてのレコードが返されます。Orders
テーブルに一致するレコードがあれば、OrderID
と OrderDate
列も返されます。一致するレコードがない場合は、これらの列は NULL 値となります。
補足
ORDER BY
句を使用して、右側テーブルの列に基づいて結果をソートしてからTOP 1
句を使用すると、最新の または 古い レコードを取得できます。ROW_NUMBER()
関数を使用して、左側テーブルの各レコードに順位を付け、WHERE
句でROW_NUMBER()
が 1 であるレコードのみを選択することもできます。
サンプルコード:顧客と注文テーブルを結合し、各顧客の最新の注文を取得
SELECT
c.CustomerID,
c.CompanyName,
o.OrderID,
o.OrderDate
FROM Customers c
LEFT JOIN Orders o ON c.CustomerID = o.CustomerID
ORDER BY o.OrderDate DESC
TOP 1;
テーブルの説明
Customers
テーブル:CustomerID
:顧客 ID (主キー)CompanyName
:会社名
Orders
テーブル:OrderDate
:注文日
クエリの実行結果
このクエリを実行すると、以下の結果が得られます。
CustomerID | CompanyName | OrderID | OrderDate
-----------+------------+---------+------------
1 | ABC Corp | 10243 | 2024-05-19
クエリの説明
SELECT
句:Customers
テーブルのCustomerID
とCompanyName
列、Orders
テーブルのOrderID
とOrderDate
列を選択します。FROM
句:Customers
テーブルとOrders
テーブルを指定します。LEFT JOIN
句:Customers
テーブルのCustomerID
列とOrders
テーブルのCustomerID
列を結合します。一致するレコードがない場合でも、Customers
テーブルのすべてのレコードが結果に含まれます。ORDER BY
句:Orders
テーブルのOrderDate
列に基づいて結果を降順にソートします。
このクエリをどのようにカスタマイズできるか
WHERE
句を追加して、特定の顧客のみに絞り込むことができます。SELECT
句に追加の列を追加して、顧客や注文に関するその他の情報を取得することができます。GROUP BY
句を使用して、各顧客の注文数を集計することができます。
SQL Server で LEFT JOIN と TOP 1 句を使用しない代替方法
サブクエリを使用して、右側テーブルから一致するレコードを 1 件のみ取得し、それを左側テーブルの各レコードと結合することができます。
SELECT
c.CustomerID,
c.CompanyName,
o.OrderID,
o.OrderDate
FROM Customers c
LEFT JOIN (
SELECT
o.CustomerID,
MAX(o.OrderID) AS OrderID,
MAX(o.OrderDate) AS OrderDate
FROM Orders o
GROUP BY o.CustomerID
) AS o ON c.CustomerID = o.CustomerID;
SELECT
c.CustomerID,
c.CompanyName,
o.OrderID,
o.OrderDate
FROM Customers c
LEFT JOIN Orders o ON c.CustomerID = o.CustomerID
WHERE ROW_NUMBER() OVER (PARTITION BY c.CustomerID ORDER BY o.OrderDate DESC) = 1;
OUTER APPLY
演算子を使用して、右側テーブルの各レコードに対して左側テーブルのすべてのレコードを処理することができます。TOP 1
句を使用して、最初の 1 件のみを取得します。
SELECT
c.CustomerID,
c.CompanyName,
o.OrderID,
o.OrderDate
FROM Customers c
OUTER APPLY (
SELECT TOP 1
o.OrderID,
o.OrderDate
FROM Orders o
WHERE o.CustomerID = c.CustomerID
ORDER BY o.OrderDate DESC
) AS o;
最適な方法の選択
使用する方法は、データ量、クエリのパフォーマンス要件、スキーマ、個人の好みによって異なります。
- データ量が少ない場合:サブクエリや
ROW_NUMBER()
関数を使用する方法がシンプルで読みやすい場合があります。 - データ量が多い場合:
OUTER APPLY
を使用すると、パフォーマンスが向上する場合があります。 - 既存のクエリに組み込む必要がある場合:
ROW_NUMBER()
関数を使用する方が簡単かもしれません。
いずれの方法を選択する場合も、クエリをテストして、期待どおりに結果が得られていることを確認してください。
sql-server outer-join