如何有效地更新具有a_id
84特定值的多行,然后针对同一0
将所有其他行设置为a_id
?
产品
p_id a_id best
111 81 99
222 81 99
666 82 99
222 83 99
111 84 99
222 84 99
333 84 99
111 85 99
222 85 99
现在我正在这样做:
update products as u set
best = u2.best
from (values
(111, 84, 1),
(222, 84, 2)
) as u2(p_id, a_id, best)
where u2.p_id = u.p_id AND u2.a_id = u.a_id
RETURNING u2.p_id, u2.a_id, u2.best
但这只会按预期更新values
中的行。如何将values
以外的行更新为0
= 84的a_id
?
意味着333的p_id
应该具有best
=0。我可以明确地包含每个p_id
,但表很大。
best
的值将始终按从1到 n 的顺序排列,由values
的顺序定义。products
表具有一百万行答案 0 :(得分:1)
假设(p_id, a_id)
是PK-或至少是UNIQUE
和NOT NULL
,这是一种方式:
UPDATE products AS u
SET best = COALESCE(u2.best, 0)
FROM products AS p
LEFT JOIN ( VALUES
(111, 84, 1),
(222, 84, 2)
) AS u2(p_id, a_id, best) USING (p_id, a_id)
WHERE u.a_id = 84
AND u.a_id = p.p_id
AND u.p_id = p.p_id
RETURNING u2.p_id, u2.a_id, u2.best;
困难之处在于,FROM
的{{1}}列表与UPDATE
等效,而您需要INNER JOIN
。此解决方法将表OUTER JOIN
添加到products
列表中(通常是多余的),以充当FROM
的左表。 然后从LEFT OUTER JOIN
到INNER JOIN
的{{1}}起作用。
要另外限制products
,请添加另一个products
子句。这使a_id = 84
表达式中的WHERE
成为多余的,但是请保留在该表达式中以避免多个连接,这些连接只会在以后被过滤。便宜点。
如果没有PK列或任何其他a_id = 84
列的组合,则可以退回到系统列VALUES
来连接UNIQUE NOT NULL
行。示例:
答案 1 :(得分:1)
从ON子句中删除条件u2.a_id = u.a_id
,并使用CASE语句将其放在分配中:
update products as u set
best = case when u2.a_id = u.a_id then u2.best else 0 end
from (values
(111, 84, 1),
(222, 84, 2)
) as u2(p_id, a_id, best)
where u2.p_id = u.p_id