サブクエリの結果を使用して、テーブルの複数の列を更新できる必要があります。簡単な例は以下のようになります-
UPDATE table1
SET (col1, col2) =
((SELECT MIN (ship_charge), MAX (ship_charge) FROM orders))
WHERE col4 = 1001;
PostgreSQLでこれを行うにはどうすればよいですか?
ヒントをありがとう!
更新:サンプルを実際のユースケースに対して単純にしすぎたことをおaびします。以下のクエリはより正確です-
UPDATE table1
SET (TOTAL_MIN_RATE, TOTAL_MAX_RATE) = (SELECT AVG(o.MIN_RATE), AVG(o.MAX_RATE)
FROM ORDR o INNER JOIN table2 ba ON (o.PAY_ACCT_ID = ba.ACCT_ID)
INNER JOIN table3 mb ON (ba.BANK_ID = mb.BANK_ID)
WHERE ba.CNTRY_ID = table1.CNTRY_ID AND
o.STUS_CD IN ('01','02','03','04','05','06') AND
((o.FRO_CRNCY_ID = table1.TO_CRNCY_ID AND o.TO_CRNCY_ID = table1.FRO_CRNCY_ID) OR
(o.TO_CRNCY_ID = table1.TO_CRNCY_ID AND o.FRO_CRNCY_ID = table1.FRO_CRNCY_ID))
GROUP BY ba.CNTRY_ID)
2つの副選択を回避したい場合は、クエリを次のように書き換えることができます。
UPDATE table1
SET col1 = o_min, col2 = o_max
FROM (
SELECT min(ship_charge) as o_min,
max(ship_charge) as o_max
FROM orders
) t
WHERE col4 = 1001
Ship_chargeにインデックスが付けられていない場合、これは2つの副選択よりも高速です。 ship_chargeがインデックス付けされている場合、おそらく大きな違いはありません
編集
Postgres 9.5以降、これは次のように書くこともできます。
UPDATE table1
SET (col1, col2) = (SELECT min(ship_charge), max(ship_charge) FROM orders)
WHERE col4 = 1001
UPDATE table1
SET
col1 = subquery.min_value,
col2 = subquery.max_value
FROM
(
SELECT
1001 AS col4,
MIN (ship_charge) AS min_value,
MAX (ship_charge) AS max_value
FROM orders
) AS subquery
WHERE table1.col4 = subquery.col4
Table1で複数の行を一度に更新する場合は、サブクエリで複数の行を返すこともできます。
これはこれを行う最も効率的な方法ではありませんが、簡単です。
UPDATE table1 SET
col1 = (SELECT MIN (ship_charge) FROM orders),
col2 = (SELECT MAX (ship_charge) FROM orders)
WHERE col4 = 1001;
1つのオプション(唯一ではない)は、2つの別々のサブクエリを使用することです。
update table1
set col1 = (select min(ship_charge) from orders),
col2 = (select max(ship_charge) from orders)
where col4 = 1001;
PostgreSQL 9.0のUPDATEの細かいマニュアル から:
標準に従って、列リスト構文では、サブセレクトなど、単一の行値式から列のリストを割り当てることができます。
UPDATE accounts SET (contact_last_name, contact_first_name) = (SELECT last_name, first_name FROM salesmen WHERE salesmen.id = accounts.sales_id);
これは現在実装されていません。ソースは独立した式のリストでなければなりません。
公式ドキュメント のように:標準アップデートを使用できますPostgreSQLアップデートの概要UPDATE table SET { column = { expression | DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [, ...] [ FROM from_list ] [ WHERE condition ]
UPDATE table1 SET TOTAL_MIN_RATE = subQuery."minRate", TOTAL_MAX_RATE = subQuery.maxRate FROM ( SELECT AVG (o.MIN_RATE) AS minRate, AVG (o.MAX_RATE) AS maxRate FROM ORDR o INNER JOIN table2 ba ON (o.PAY_ACCT_ID = ba.ACCT_ID) INNER JOIN table3 mb ON (ba.BANK_ID = mb.BANK_ID) WHERE ba.CNTRY_ID = table1.CNTRY_ID AND o.STUS_CD IN ( '01', '02', '03', '04', '05', '06' ) AND ( ( o.FRO_CRNCY_ID = table1.TO_CRNCY_ID AND o.TO_CRNCY_ID = table1.FRO_CRNCY_ID ) OR ( o.TO_CRNCY_ID = table1.TO_CRNCY_ID AND o.FRO_CRNCY_ID = table1.FRO_CRNCY_ID ) ) GROUP BY ba.CNTRY_ID ) subQuery;
UPDATE table1 SET ( TOTAL_MIN_RATE, TOTAL_MAX_RATE ) = ( SELECT AVG (o.MIN_RATE) AS minRate, AVG (o.MAX_RATE) AS maxRate FROM ORDR o INNER JOIN table2 ba ON (o.PAY_ACCT_ID = ba.ACCT_ID) INNER JOIN table3 mb ON (ba.BANK_ID = mb.BANK_ID) WHERE ba.CNTRY_ID = table1.CNTRY_ID AND o.STUS_CD IN ( '01', '02', '03', '04', '05', '06' ) AND ( ( o.FRO_CRNCY_ID = table1.TO_CRNCY_ID AND o.TO_CRNCY_ID = table1.FRO_CRNCY_ID ) OR ( o.TO_CRNCY_ID = table1.TO_CRNCY_ID AND o.FRO_CRNCY_ID = table1.FRO_CRNCY_ID ) ) GROUP BY ba.CNTRY_ID );
UPDATE FROM
を使用することは、単純な副選択がない場合に適したソリューションです。このUPDATE
では、photos
テーブルのevent_profile_id
を、写真が属する写真セットの所有者(イベントプロファイルも所有者)に設定したかった。
UPDATE photos
SET event_profile_id=photos_and_events.event_profile_id
FROM (
SELECT
ph.id photo_id,
pr.id event_profile_id
FROM photos ph, profiles pr, photo_sets ps
WHERE ph.main_photo_set_id=ps.id AND ps.owner_profile_id=pr.id
) AS photos_and_events
WHERE photos.id=photos_and_events.photo_id;