サブクエリの基礎

サブクエリとは、SELECT、INSERT、UPDATE、または DELETE の各ステートメントの内部、または別のサブクエリの内部で入れ子になっているクエリです。サブクエリは、式が使えるところであればどこにでも使用できます。次の例では、SELECT ステートメント内にある MaxUnitPrice という列に対する式としてサブクエリを使用します。

USE AdventureWorks2008R2;
GO
SELECT Ord.SalesOrderID, Ord.OrderDate,
    (SELECT MAX(OrdDet.UnitPrice)
     FROM AdventureWorks.Sales.SalesOrderDetail AS OrdDet
     WHERE Ord.SalesOrderID = OrdDet.SalesOrderID) AS MaxUnitPrice
FROM AdventureWorks2008R2.Sales.SalesOrderHeader AS Ord

サブクエリは内部クエリや内部選択と呼ばれることもあります。また、サブクエリを含むステートメントは外部クエリや外部選択と呼ばれます。

サブクエリを含む Transact-SQL ステートメントの多くは、サブクエリを使う代わりに結合を使って表現することもできます。サブクエリでしか発生しない問題もあります。通常、Transact-SQL では、サブクエリを含むステートメントと、意味は同じでもサブクエリを含まないステートメントとの間にパフォーマンスの違いはありません。ただし、存在を検査する必要がある場合には、結合によってパフォーマンスが向上することもあります。それ以外の場合は、入れ子になったクエリを外側のクエリの結果ごとに処理し、重複が確実に解消されるようにする必要があります。このような場合、結合のアプローチを使った方が良い結果になります。次の例は、サブクエリ SELECT と結合の SELECT が同じ結果を返すことを示しています。

/* SELECT statement built using a subquery. */
SELECT Name
FROM AdventureWorks2008R2.Production.Product
WHERE ListPrice =
    (SELECT ListPrice
     FROM AdventureWorks2008R2.Production.Product
     WHERE Name = 'Chainring Bolts' );

/* SELECT statement built using a join that returns
   the same result set. */
SELECT Prd1. Name
FROM AdventureWorks2008R2.Production.Product AS Prd1
     JOIN AdventureWorks2008R2.Production.Product AS Prd2
       ON (Prd1.ListPrice = Prd2.ListPrice)
WHERE Prd2. Name = 'Chainring Bolts';

1 つ上のレベルの SELECT ステートメントの中で入れ子になったサブクエリの SELECT の構成要素は、次のようになります。

  • 標準の選択リスト構成要素を含んでいる標準の SELECT クエリ

  • 1 つ以上のテーブル名またはビュー名を含んでいる標準の FROM 句

  • オプションの WHERE 句

  • オプションの GROUP BY 句

  • オプションの HAVING 句

サブクエリの SELECT クエリは常にかっこで囲みます。このステートメントには COMPUTE 句および FOR BROWSE 句は指定できませんが、TOP 句も指定された場合にのみ ORDER BY 句を含むことができます。

サブクエリは、1 つ上のレベルの SELECT、INSERT、UPDATE、または DELETE の各ステートメントの WHERE 句または HAVING 句の中、あるいは別のサブクエリの中で入れ子にできます。32 レベルまで入れ子にできますが、上限はクエリの複雑さと使用可能なメモリによって変わります。個々のクエリでは 32 レベルまで入れ子にすることはできません。サブクエリは、単一の値を返す限り、式が使えるところであればどこにでも使用できます。

あるテーブルがサブクエリにのみ現れていて、1 つ上のレベルのクエリに現れていない場合、そのテーブルの列は出力 (1 つ上のレベルのクエリの選択リスト) に含めることはできません。

サブクエリを含むステートメントは、通常、次の形式のいずれかになります。

  • WHERE expression [NOT] IN (subquery)

  • WHERE expression comparison_operator [ANY | ALL] (subquery)

  • WHERE [NOT] EXISTS (subquery)

Transact-SQL ステートメントの中には、サブクエリが独立したクエリであるように評価されるものがあります。概念的には、サブクエリの結果が 1 つ上のレベルのクエリに代入されることになります。ただし、サブクエリを含む Transact-SQL ステートメントが、Microsoft SQL Server によってこのように処理されるとは限りません。

サブクエリの種類は、大きく 3 つに分けられます。具体的には、次のように大別されます。

  • IN で導かれるリスト、または ANY あるいは ALL で修飾された比較演算子で導かれるリストを操作するサブクエリ

  • 修飾されていない比較演算子で導かれ、単一の値を返す必要があるサブクエリ

  • EXISTS で導かれる、存在を検査するサブクエリ