这里不需要 plpgsql。
一次处理很多行:
UPDATE list l
SET state = u.state
FROM (
SELECT li.pk_col
, CASE WHEN h.hist_date > (now() - interval '1 week') THEN 2
WHEN p.part_number IS NULL THEN 1
ELSE 2
END AS state
FROM list li
LEFT JOIN part p USING (part_number)
LEFT JOIN history h USING (part_number)
WHERE li.refNo = <some value>
) u
WHERE l.pk_col = u.pk_col -- insert actual pk column
AND l.state IS DISTINCT FROM u.state;
或者,更快,但在没有子查询的情况下更冗长:
UPDATE list l
SET state = CASE WHEN h.hist_date > (now() - interval '1 week') THEN 2
WHEN p.part_number IS NULL THEN 1
ELSE 2 END
FROM list li
LEFT JOIN part p USING (part_number)
LEFT JOIN history h USING (part_number)
WHERE li.refNo = <some value>
AND l.pk_col = li.pk_col -- insert actual pk column
AND l.state IS DISTINCT FROM
CASE WHEN h.hist_date > (now() - interval '1 week') THEN 2
WHEN p.part_number IS NULL THEN 1
ELSE 2 END
我假设 column history.hist_date
,因为您没有指定。
替换pk_col
为您的实际主键列。你没有指定。
您不应该使用不带引号的混合大小写标识符,例如refNo
. 使用refno
或"refNo"
。
最后一个条件避免了已经具有预期值的WHERE
空更新。state
如果在您的情况下不能发生这种情况,请省略。大多数时候,人们往往会忘记它是对性能的改进。
为此,您需要相关列上的索引。PK 列会自动编制索引。您还需要一个 for each part_number
、 forlist.refNo
和 for history.hist_date
。
理想情况下,您应该有一个多列索引,history
例如:
CREATE INDEX h_multi_idx ON history (part_number, hist_date DESC);
在这种情况下,将胜过每一列的一个索引。
几行的简单版本
另一种方法是相关子查询 - 更简单地更新单行或几行:
UPDATE list l
SET state = COALESCE((
SELECT CASE WHEN h.hist_date > (now() - interval '1 week') THEN 2 ELSE 3 END
FROM part p
LEFT JOIN history h USING (part_number)
WHERE p.part_number = l.part_number
), 1)
WHERE refNo = <some value>;
对于很多行,相关的子查询不能很好地扩展。
请注意,即使state
已经具有预期值,这也会更新该行。
更新评论
对于 in 上的重复项(part_number)
和history
(假设)在or上没有重复项,这是(许多可能的)解决方案之一:(part_number)
part
list
UPDATE list l
SET state = u.state
FROM (
SELECT DISTINCT ON (h.part_number)
li.pk_col
, CASE WHEN h.hist_date > (now() - interval '1 week') THEN 2
WHEN p.part_number IS NULL THEN 1
ELSE 2
END AS state
FROM list li
LEFT JOIN part p USING (part_number)
LEFT JOIN history h USING (part_number)
WHERE li.refNo = <some value>
ORDER BY h.part_number, h.hist_date DESC NULLS LAST
) u
WHERE l.pk_col = u.pk_col -- insert actual pk column
AND l.state IS DISTINCT FROM u.state;
可能有更有效的方法。取决于缺失的信息。