use*_*122 31 postgresql subquery
我需要能够使用子查询的结果更新表上的多个列.一个简单的例子如下所示 -
UPDATE table1
SET (col1, col2) =
((SELECT MIN (ship_charge), MAX (ship_charge) FROM orders))
WHERE col4 = 1001;
Run Code Online (Sandbox Code Playgroud)
我怎么能在PostgreSQL中做到这一点?
谢谢你的任何提示!
更新:我为使样本对我的实际用例过于简单而道歉.以下查询更准确 -
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)
Run Code Online (Sandbox Code Playgroud)
a_h*_*ame 38
如果要避免两个子选择,可以像下面这样重写查询:
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
Run Code Online (Sandbox Code Playgroud)
如果ship_charge未编入索引,则应该比两个子选择更快.如果ship_charge被编入索引,则可能没有太大的区别
编辑
从Postgres 9.5开始,这也可以写成:
UPDATE table1
SET (col1, col2) = (SELECT min(ship_charge), max(ship_charge) FROM orders)
WHERE col4 = 1001
Run Code Online (Sandbox Code Playgroud)
wil*_*aks 18
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
Run Code Online (Sandbox Code Playgroud)
如果要在table1中一次更新多行,也可以在子查询中返回多行.
这不是最有效的方法,但它很简单:
UPDATE table1 SET
col1 = (SELECT MIN (ship_charge) FROM orders),
col2 = (SELECT MAX (ship_charge) FROM orders)
WHERE col4 = 1001;
Run Code Online (Sandbox Code Playgroud)
一个选项(但不是唯一的选项)是使用两个单独的子查询:
update table1
set col1 = (select min(ship_charge) from orders),
col2 = (select max(ship_charge) from orders)
where col4 = 1001;
Run Code Online (Sandbox Code Playgroud)
根据标准,列列表语法应允许从单个行值表达式分配列的列表,例如子选择:
Run Code Online (Sandbox Code Playgroud)UPDATE accounts SET (contact_last_name, contact_first_name) = (SELECT last_name, first_name FROM salesmen WHERE salesmen.id = accounts.sales_id);目前尚未实现 - 源必须是独立表达式列表.