SQL 結合の関連テーブルから最初の行のみを選択する
データベース結合では、多くの場合、関連するテーブルから複数の一致する行が取得されます。 この記事では、複数の一致が存在する場合でも、結合を親レコードごとに 1 行に制限する必要があるシナリオについて説明します。 これにより、クエリ出力で結果が重複することがなくなります。
チャレンジ
Orders
と LineItems
という 2 つのテーブルについて考えます。 通常、注文には 1 つの品目がありますが、注文によっては複数の品目がある場合があります。 注文の詳細を表示するときは、注文ごとに 1 つの明細項目のみを表示することが重要です。そうしないと、重複によって結果が乱雑になります。
初期アプローチ (とその失敗)
結合内で TOP 1
を直接使用しようとする単純な試みは、内部クエリが外部テーブルの列 (OrderID
など) にアクセスできないため失敗します。
解決策: CROSS APPLY と INNER JOIN
最も効果的なアプローチは、CROSS APPLY
(SQL Server 2005 以降で利用可能) または古いバージョンの賢い INNER JOIN
を使用します。
CROSS APPLY の使用 (SQL Server 2005 以降)
CROSS APPLY
は、外部テーブルの行ごとに行セットを生成し、相関サブクエリを有効にします。 次に、このサブクエリはフィルター処理を行い、関連テーブルから 1 つの行を選択します。
<code class="language-sql">SELECT Orders.OrderNumber, LineItems2.Quantity, LineItems2.Description FROM Orders CROSS APPLY ( SELECT TOP 1 LineItems.Quantity, LineItems.Description FROM LineItems WHERE LineItems.OrderID = Orders.OrderID ) LineItems2</code>
INNER JOIN の使用 (SQL Server 2005 以前)
CROSS APPLY
が欠落している古い SQL Server バージョンの場合、サブクエリを含む INNER JOIN
は同じ結果をもたらします。
<code class="language-sql">SELECT Orders.OrderNumber, LineItems.Quantity, LineItems.Description FROM Orders INNER JOIN LineItems ON LineItems.LineItemGUID = ( SELECT TOP 1 LineItemGUID FROM LineItems WHERE OrderID = Orders.OrderID )</code>
決定論に関する重要な注意:
TOP 1
節は、ORDER BY
節がないと本質的に非決定的です。 一貫した結果を保証するには (つまり、常に 同じ の「最初の」行項目を選択する)、内部クエリ内に ORDER BY
句を追加します (例: ORDER BY LineItems.SomeColumn
)。 これにより、ラインアイテムの予測可能な選択が保証されます。
以上がSQL で関連テーブルの最初の行のみに効率的に結合するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。