WITH
允许您定义用于SELECT
查询的“临时表”。比如,我最近写了这样的查询,两组之间计算的变化:
-- Let o be the set of old things, and n be the set of new things.
WITH o AS (SELECT * FROM things(OLD)),
n AS (SELECT * FROM things(NEW))
-- Select both the set of things whose value changed,
-- and the set of things in the old set but not in the new set.
SELECT o.key, n.value
FROM o
LEFT JOIN n ON o.key = n.key
WHERE o.value IS DISTINCT FROM n.value
UNION ALL
-- Select the set of things in the new set but not in the old set.
SELECT n.key, n.value
FROM o
RIGHT JOIN n ON o.key = n.key
WHERE o.key IS NULL;
通过定义“表” o
和n
在上面,我是能够避免重复表达things(OLD)
和things(NEW)
。
当然,我们可以使用FULL JOIN
来消除UNION ALL
,但在我的特殊情况下我无法做到这一点。
如果我正确理解您的查询,它这样做:
我不认为WITH
会简化你的情况。它可能会稍微更优雅的使用FROM
条款,但:
update global.prospect psp
set status = status || '*'
from (select psp_id
from global.prospect
where status = 'new' or status = 'reset'
order by request_ts
limit 1
) p2
where psp.psp_id = p2.psp_id
returning psp.*;
未经检验。让我知道它是否有效。
这几乎是你有什么已经,除了:
这可以很容易地扩展到更新多行。在使用子查询表达式的版本中,如果子查询更改为产生多行,则查询将失败。
我没有在子查询中别名global.prospect
,所以它更容易阅读。由于这使用了FROM
子句,因此如果意外引用正在更新的表,则会出现错误。
在您的版本中,每个单项都会遇到子查询表达式。虽然PostgreSQL应该对此进行优化并且只对表达式进行一次评估,但如果您不小心引用psp
中的列或添加易失性表达式,则此优化将消失。
根据文档,在PostgreSQL 9.1中添加了在INSERT和UPDATE语句之上使用WITH [RECURSIVE]。 – 2012-01-04 04:08:20
@JoeyAdams - 使用dml - 理解另一层洋葱 – 2012-01-04 04:16:34