「親」というマスターテーブルと「子」という関連テーブルがあります
次に、マスターテーブルに対してクエリを実行して、このように子テーブルの合計でいくつかの値を更新します。
UPDATE master m SET
quantity1 = (SELECT SUM(quantity1) FROM childs c WHERE c.master_id = m.id),
quantity2 = (SELECT SUM(quantity2) FROM childs c WHERE c.master_id = m.id),
count = (SELECT COUNT(*) FROM childs c WHERE c.master_id = m.id)
WHERE master_id = 666;
これは期待どおりに機能しますが、基本的に同じ結果に対して複数のSELECTクエリを実行するため、適切なスタイルではありません。それを最適化する方法はありますか?(最初にクエリを実行して値を保存することはオプションではありません。
私はこれを試しました:
UPDATE master m SET (quantity1, quantity2, count) = (
SELECT SUM(quantity1), SUM(quantity2), COUNT(*)
FROM childs c WHERE c.master_id = m.id
) WHERE master_id = 666;
しかし、それは機能しません。
更新:これが解決策です、everbodyのおかげで:
あなたはこのようなことをすることができます:
UPDATE master m
INNER JOIN childs c ON m.master_id = c.master_id
SET master.quantity1 = c.quantity1,
master.count = 1
一度に1つの子レコードしかない場合。ただし、結合されたテーブルでSUM()のようなグループ関数を使用したい場合は機能しません。「groupby」の部分を残すと「groupfunctionの無効な使用」が発生するか、「GROUPBYc.master_id」を使用するとSQL構文にエラーが発生します。
-- This doesnt work :(
UPDATE master m
INNER JOIN childs c ON m.master_id = c.master_id
SET master.quantity1 = SUM(c.quantity1),
master.count = COUNT(c.*)
GROUP by c.master_id
解決策は、サブクエリでJOINを使用することです。
UPDATE master m
INNER JOIN
(
SELECT master_id,
SUM(quantity1) as quantity1,
COUNT(*) as count
FROM childs c
GROUP BY master_id
) c
ON c.master_id = m.master_id
SET m.quantity1 = c.quantity1,
m.count = c.count
WHERE m.master_id = 666;
ただし、これにより子テーブルからすべての行がプルされるため、元のSQLのように多くのサブクエリを使用するよりもオーバーヘッドが大きくなる可能性があります。したがって、必要な行のみを取得するには、結合されたテーブルにWHERE句を追加する必要があります。
もう1つの興味深いアプローチは、この構文です。これは、WHERE句を使用したJOINと同じですが、すべての行を同じ値で更新する場合にのみ使用する必要があり、サブクエリの結果は次のようになります。結果に追加され、他の列と同じように使用できます。
UPDATE master m,
(
SELECT SUM(c.quantity1) as sum_of_quantity,
COUNT(*) as rowcount FROM child c WHERE c.master_id = 666
) as c
SET m.quantity1 = c.sum_of_quantity,
m.count = c.rowcount
WHERE m.master_id = 666;