SQL Serverのサブクエリ(サブクエリ)
- 12-09-2022
- Toanngo92
- 0 Comments
Mục lục
サブクエリ(サブクエリ)
SELECTステートメントまたはクエリを使用して、別のSELECTステートメントまたはクエリの基準として使用されるレコードを返すことができます。外側のクエリは親クエリと呼ばれ、内側のクエリはサブクエリと呼ばれます。サブクエリの目的は、結果を外部クエリに返すことです。つまり、内部クエリステートメントは、外部クエリの条件で使用される1つまたは複数の列を返す必要があります。
サブクエリの最も単純な形式は、1つの列のみを返すクエリです。親クエリは、このサブクエリの結果を「=」で使用できます。構文:
SELECT <ColumnName> FROM <table> WHERE <ColumnName> = (SELECT <ColumnName> FROM <Table> WHERE <ColumnName> = <Condition>)
サブクエリでは、最も内側のSELECTステートメントが最初に実行され、その結果が外側のSELECTステートメントの基準として渡されます。
最新の注文の期日と納期を決定する必要がある状況を考えてみましょう。
例えば:
SELECT DueDate,ShipDate FROM Sales.SalesOrderHeader WHERE Sales.SalesOrderHeader.OrderDate = (SELECT MAX(OrderDate) FROM Sales.SalesOrderHeader)
ここでは、サブクエリを使用して目的の出力を実現しました。内部クエリまたはサブクエリは、最新の注文日を取得します。次に、この結果は外部クエリに渡され、すべての注文の期日と配達日、その特定の日に履行された注文が表示されます。
内部クエリによって返された結果に基づいて、サブクエリはスカラーサブクエリ( scalar )または複数値クエリ( multi-valued )のいずれかに分類できます。
次の説明が利用可能です。
- スカラーサブクエリは単一の値を返します。ここでは、単一の結果を処理するために外部クエリを作成する必要があります。
- 複数値のサブクエリは、単一列のテーブルと同じ結果を返します。ここでは、複数の可能な結果を処理するために、外部クエリを作成する必要があります。
複数値クエリの操作
「=」演算子をサブクエリで使用する場合、サブクエリは単一のスカラー値を返す必要があります。複数の値が返された場合、エラーが発生し、クエリは処理されません。このような場合、クエリが1つの列を返すが、1つ以上の行を返す場合は、 ANY、ALL、IN、およびEXISTSキーワードをSELECTステートメントのWHERE句とともに使用できます。
これらのキーワードは、述語とも呼ばれ、複数値のクエリで使用されます。たとえば、役職が「ResearchandDevelopmentManager」の従業員の名前と姓をすべて表示する必要があるとします。ここでは、その役職を持つ複数の従業員がいる可能性があるため、内部クエリは複数の行を返す場合があります。外部クエリが内部クエリの結果を使用できるようにするには、INキーワードを使用する必要があります。
例えば:
SELECT FirstName,LastName FROM Person.Person WHERE Person.Person.BusinessEntityID IN (SELECT BusinessEntityID FROM HumanResources.Employee WHERE JobTitle='Research and Development Manager');
結果が比較に等しい1行を含む内部クエリである場合、 SOMEまたはANYキーワードのどちらがtrueと評価されます。スカラー値を値の列と比較します。 SOMEとANYは同等であり、どちらも同じ結果を返します。それらはめったに使用されません。
サブクエリを使用する際のいくつかのガイドライン:
- データ型ntext、text、imageは、サブクエリのSELECTでは使用できません
- 比較演算子で導入されたサブクエリSELECTリストには、式または列名を1つだけ含めることができます。
- ANYまたはALLキーワードを使用して比較演算子を操作する場合のサブクエリでは、GROUPBY句とHAVING句を使用できません。
- GROUPBY句を含むサブクエリでDISTINCTキーワードを使用することはできません。
- サブクエリを使用するときにTOPも指定されている場合にのみ、ORDERBYを指定できます。
スカラーおよび複数値のサブクエリに加えて、独立したサブクエリと相関したサブクエリから選択することもできます。それらは次のように定義されます。
- スタンドアロンサブクエリは、外部クエリに依存することなく、スタンドアロンクエリとして記述されます。独立したサブクエリは、外部クエリが実行され、その結果が外部クエリに渡されるときに1回処理されます。
- 関連するサブクエリは、外部クエリの1つ以上の列を参照するため、外部クエリに依存します。関連するサブクエリは、外部クエリとは別に実行することはできません。
EXISTSキーワードは、サブクエリで返される行の存在を確認するためにサブクエリで使用されます。実際にはデータを返さず、TRUEまたはFALSEを返します
EXISTSキーワードを含むサブクエリの構文:
SELECT <ColumnName> FROM <table> WHERE [NOT] EXISTS (subquery_statement)
例えば:
use AdventureWorks2019 go SELECT FirstName,LastName FROM Person.Person AS p WHERE EXISTS (SELECT * FROM HumanResources.Employee AS e WHERE JobTitle='Research and Development Manager' AND p.BusinessEntityID=e.BusinessEntityID )
ここで、内部サブクエリは「Research and Development Manager」の役職に一致するすべてのレコードを取得し、BusinessEntityIDにはPersonテーブルのそのレコードに一致するBusinessEntityIDがあります。これらの条件の両方に一致するレコードがない場合、内部サブクエリは行を返しません。ただし、以下のコードは、指定された条件が満たされているため、2行を返します。
同様に、 EXISTSの否定句であるNOTEXISTSキーワードを使用できます。
ネストされたサブクエリ(ネストされたサブクエリ)
別のサブクエリ内で定義されたサブクエリは、ネストされたサブクエリと呼ばれます。 adventureworks2019でカナダの人の名前を取得して表示する状況を考えると、Sales.SalesTerritoryテーブルはPerson.Personテーブルに関連していないため、この情報を直接取得する方法はありません。したがって、ネストされたサブクエリが解決策になる可能性があります。
例えば:
SELECT LastName, FirstName FROM Person.Person WHERE BusinessEntityID IN (SELECT BusinessEntityID FROM Sales.SalesPerson WHERE TerritoryID IN (SELECT TerritoryID FROM Sales.SalesTerritory WHERE Name='Canada'))
相関クエリ(関連クエリ)
サブクエリを含む複数のクエリでは、サブクエリは1回だけ評価され、親クエリに必要な値を提供します。これは、ほとんどのクエリで、サブクエリが親クエリを参照しないため、サブクエリの値が同じままであるためです。
ただし、サブクエリが親クエリを参照している場合は、親クエリの反復ごとにサブクエリを再評価する必要があります。これは、サブクエリの検索条件が親クエリの特定のレコードの値に依存するためです。
サブクエリが親クエリからパラメータを受け取る場合、それは関連サブクエリと呼ばれます。 2012年以降に連絡先情報が最後に変更された人のすべてのBusinessEntityIDを取得する状況を考えてみます。これを行うには、関連するサブクエリを次のように使用できます。
SELECT a.BusinessEntityID FROM Person.BusinessEntityContact a WHERE a.ContactTypeID IN (SELECT c.ContactTypeID FROM Person.ContactType c WHERE YEAR (a.ModifiedDate) >= 12)
コードスニペットでは、内部クエリは、連絡先情報が2012年以降に最後に変更されたすべての人の連絡先タイプIDを取得します。これらの結果は、外部クエリに渡され、結果はPerson.BusinessEntityContactテーブルのContactTypeIDと一致します。