今回は、SELECT文を入れ子にした副問い合わせ(サブクエリー)を説明します。
まずは、本講座の第1回(「SQLの基礎SELECT文を覚えよう」)で解説した「IN」をもう一度復習しましょう。次の例題を実行してみてください。
【例1】
SELECT * FROM Customers WHERE CustomerID IN ('ALFKI', 'ANATR', 'ANTON')
IN句を使用すると、“ ( ) ”の中に指定された値を持つ行のみが抽出され、結果として表示されます。例1では、CustomerIDが「ALFKI」か「ANATR」か「ANTON」の顧客のみ、Customersテーブルから抽出されて表示されているのが分かりますね。これは、例2のように、すべてをORで条件指定した場合と、結果は同じです。
【例2】
SELECT * FROM Customers WHERE CustomerID = 'ALFKI' OR CustomerID = 'ANATR' OR CustomerID = 'ANTON'
この例のように、同じカラムに対する複数のORを並べるより、IN句を使用した方が、より判読しやすいSQL文の記述ができる場合が多いです。
また、IN句は、NOTで否定することもできます。次の例では、例1とは逆で、CustomerIDがALFKI、ANATR、ANTONのどれでもない行が結果として返されます。
【例3】
SELECT * FROM Customers WHERE CustomerID NOT IN ('ALFKI', 'ANATR', 'ANTON')
では次に、「過去に注文があった顧客のリスト」を表示させてみましょう。
注文を顧客単位に管理しているテーブルは「Orders」テーブルですので、OrdersテーブルにCustomerIDが保存されている顧客が、過去に注文があった顧客と見なすことができます。では、そのIDを表示してみましょう。
【例4】
SELECT CustomerID FROM Orders
同じIDが複数表示されているので、「同じCustomerIDは1度だけ表示される」ようにするためには、例5のようにDISTINCTを使用します。
【例5】
SELECT Distinct(CustomerID) FROM Orders
このように、DISTINCTを使用すると、同じ値は1つにまとめられて表示されます。
さて、ここからが本題です。例5のCustomerIDの結果を、例1のIN句の“ ( ) ”の値のリストとすることで、過去に注文があった顧客のリストを表示させましょう。次のSQL文を実行してみてください。
【例6】
SELECT * FROM Customers WHERE CustomerID IN ( SELECT Distinct(CustomerID) FROM Orders )
この例では、IN句の条件である“ ( ) ”の値のリストを、SELECT文で置き換えています。IN句の中のSELECT文が先に実行され、CustomerIDのリストを生成し、そのCustomerIDに含まれている顧客データを表示します。
このように、SELECT文の結果を、ほかのSELECT文の一部として使用することが可能です。これを、副問い合わせ(サブクエリー)と呼びます。
では次に、例6とは逆に、「いままで1度も注文をしていない顧客」を表示してみましょう。
【例7】
SELECT * FROM Customers WHERE CustomerID NOT IN ( SELECT Distinct(CustomerID) FROM Orders )
例3と同じように、INの前にNOTを入れることで、条件を逆にすることが可能です。
INと同じような使われ方をする句に、ANYとSOME、ALL、EXISTSがあります。今回は、ANYとSOMEを使ってみましょう。
次のSQL文を実行してみてください。
【例8】
SELECT * FROM Customers WHERE CustomerID = ANY ( SELECT Distinct(CustomerID) FROM Orders )
結果は、例6と同じです。ANYは、「値リストとして指定された値のいずれかの値」を指定します。例えば、「CustomerID = ANY('ALFKI', 'ANATR', 'ANTON') 」とすれば、CustomerIDが「ALFKI」「ANATR」「ANTON」の3つの値のうちいずれかと合致すれば、その行が結果リストとして返されることになります(実際には、ANYの後ろの“ ( ) ”の中には、サブクエリーのみ指定できます)。
では、INと何が違うか、というと、ANYの前に比較演算子が指定されている点です。例8では「=」を使用しましたが、ANYはほかのすべての比較演算子と組み合わせて使うことができます。
【例9】
SELECT * FROM Products WHERE UnitPrice > ANY ( SELECT UnitPrice FROM "Order Details" )
例9では、Order Detailsに保存されている単価(UnitPrice)のいずれかよりも高い単価を持つProductをリストアップします(あまり現実的な例ではありません)。
このように、ANYはさまざまな使い方ができますが、今回の例に示すように、ほかのSQL文で置き換え可能なため、実際にはあまり使われません。なお、SOMEは、SQL92ではANYと同義です。
今回は、「副問い合わせ(サブクエリー)」を紹介しました。次回は、サブクエリーの応用について解説予定です
Copyright © ITmedia, Inc. All Rights Reserved.