サブクエリは、別のクエリに使用するデータを見つけるための強力な方法です。これらは、これらのクエリをより効率的かつ保守しやすくするために、SELECTおよびUPDATEステートメントでよく使用されます。
UPDATEステートメントでサブクエリを使用する方法はいくつかあります。それぞれを見てみましょう。
SETとサブクエリ
最初に説明する方法は、UPDATEステートメントのSET句でサブクエリを使用することです。
次のような商品の表があったとしましょう:
[テーブルID=29 /]
会社が販売するさまざまな製品に関するいくつかの情報が格納されています。
会社が「Couch」製品(製品ID 1)の価格を上げることを決定したと想定します。ただし、特定の価格を設定するのではなく、最も高価な製品よりも20%高くしたいと考えています。
これを行うには、SET句でサブクエリを使用できます。個別のステートメントを使用することもできますが、単一のステートメントを使用して維持する方が簡単です。
私たちの声明は次のようになります:
UPDATE product SET price = ( SELECT MAX(price) * 1.2 FROM product ) WHERE product_id = 1;
SET句にサブクエリが含まれていることがわかります。このサブクエリは、製品テーブルの価格列のMAX値を検索し、1.2を掛けて20%を加算します。最後に、WHERE句はサブクエリの外側にあり、1のproduct_idのみを更新します。これは、サブクエリではなくUPDATEに適用されるためです。
これにより、次の変更が発生します。
[テーブルID=30 /]
SETおよび相関サブクエリ
UPDATEステートメントでサブクエリを使用する別の方法は、相関サブクエリを使用することです。
前の例と同じように機能します。ただし、相関サブクエリは、外部ステートメントを参照するサブクエリであり、UPDATEステートメントの一部である可能性があります。
前の例のデータ(製品テーブル)を使用して、会社は注文されていないすべての製品を非アクティブ化する必要があります。このためのデータはorder_lineテーブルに保存されます。
相関サブクエリとして記述した場合、クエリは次のようになります。
UPDATE product p SET active = ( SELECT CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE 'N' END FROM order_line o WHERE o.product_id = p.product_id );
サブクエリは、CASEステートメントを使用してCOUNT関数を実行し、COUNTの値に応じて戻り値がYかNかを判別します。 product_idごとに計算され、外部クエリと一致します。
これにより、一部の製品がYに設定され、他の製品がNに設定されたアクティブな列になります:
[テーブルID=31 /]
サブクエリよりも大きい場所
WHERE句でサブクエリを使用することもできます。前の例と同様に、これを実行して、更新する値を見つけるという別の手順を削除してから、クエリを実行して値を更新することができます。
前の手順の例で作業を続けることができます。会社が平均より高い価格の製品をアクティブ化することを望んでいると想定します。これを行うには、WHERE句にサブクエリを追加します。
まず、すべての製品を非アクティブ化します。
UPDATE product SET active = ’N’;
次に、サブクエリを使用してテーブルを更新します。
UPDATE product SET active = 'Y' WHERE price > ( SELECT AVG(price) FROM product );
これにより、平均を上回る価格のすべてのレコードのアクティブ値がYに設定されます。
テーブルは次のようになります:
[テーブルID=32 /]
平均を上回っているため、アクティブな値がYの2つのレコードが表示されます。
この種のクエリは、<や>=などの単一の値を許可する他の演算子を使用して実行することもできます。
サブクエリの場所
また、WHERE句でIN演算子を使用してサブクエリを使用することもできます。
これは、単一の値に大なり演算子を使用した前の例に似ています。 IN演算子は複数の値に適用できます。
このカテゴリで唯一の商品である一部の商品の価格を更新したいとします。価格を半分にする必要があります。
クエリは次のようになります:
UPDATE product SET price = price / 2 WHERE category_id IN ( SELECT category_id FROM product GROUP BY category_id HAVING COUNT(*) = 1 );
サブクエリは、COUNTが1であるすべてのcategory_id値を検索します。サブクエリのSELECT部分にCOUNTを含める必要はありませんが、そうすると、クエリにエラーが表示されます。
UPDATEステートメントは、カテゴリがサブクエリの基準を満たす価格を更新します。
結果は次のようになります:
[テーブルID=33 /]
データは非常によく似ています。ただし、カテゴリIDが1の製品は、そのカテゴリで唯一の製品であるため、元のコストの半分に価格が更新されています。
UPDATEサブクエリ
最後に、更新するテーブルのUPDATEステートメントでサブクエリを使用できます。
前の例では、productテーブルを使用しました。ただし、productテーブルの代わりにサブクエリを使用すると、更新可能な結果セットが返されます。
結果セットは、VIEWオブジェクトを作成して更新しようとする場合と同様に、更新可能である必要があります。シンプルで主キーを持っている必要があります。
したがって、前の例を使用して、会社がカテゴリ4にあるすべての製品のカテゴリをカテゴリ5に変更したいとします。
クエリは次のようになります:
UPDATE ( SELECT product_id, category_id FROM product) SET category_id = 5 WHERE category_id = 4;
これは、概念を示す簡単な例です。テーブルは、テーブルの2つの列のみを表示するSELECTステートメントに置き換えられました。
このクエリの結果は次のようになります:
[テーブルID=34 /]
WHERE句をUPDATEステートメントに移動しても同じ結果を受け取ることができます:
UPDATE ( SELECT product_id, category_id FROM product WHERE category_id = 4) SET category_id = 5;
結論
UPDATEステートメントでサブクエリを使用すると、クエリの保守性を向上させることができます。また、2つ以上のクエリを1つのクエリに圧縮することで、データの更新に必要な手順の数を減らすことができます。