简体   繁体   English

Postgres SQL UPDATE基于前一个SELECT的结果

[英]Postgres SQL UPDATE based on result of a previous SELECT

In Postgres 10 I want to perform an UPDATE twice. 在Postgres 10中,我想要执行两次UPDATE。 First UPDATE should run no matter what, updating the alwaysupdate column. 无论如何都要运行第一个UPDATE,更新alwaysupdate列。 And the second UPDATE should run only if the SELECT statement below returns a row count of 0, which means sometimesupdate should get updated only if all of the rows in mytable where mykey = 100 have sometimesupdate set to null . 但第二个更新应该只运行,如果下面的SELECT语句返回0行数,这意味着sometimesupdate应该得到更新只有当所有的行mytable其中mykey = 100已经sometimesupdate设置为null

-- Run no matter what, updating 'alwaysupdate'
update mytable set alwaysupdate = now() where keyA = 100 and keyB = 200

-- Check the number of rows where 'sometimesupdate' has a value
select count(*) from mytable where keyB = 200 and sometimesupdate is not null

-- If 'sometimesupdate' is null for all rows above, give it a value in this row
update mytable set sometimesupdate = now() where keyA = 100 and keyB = 200

What's the most efficient way to do this? 最有效的方法是什么? Is it possible to combine it into a single SQL statement? 是否可以将它组合成一个SQL语句? Otherwise multiple statements wrapped in a transaction? 否则多个语句包含在一个事务中? Otherwise a function if necessary. 如有必要,否则为其他功能

Try this 尝试这个

if count is equal to zero then update to now() otherwise retain the old value of sometimesupdate 如果count等于零,则更新到now()否则保留onceupdate的旧值

update mytable as A
 set alwaysupdate = now(),
 sometimesupdate = (case when (
       select count(*) from mytable as B where B.keyB = A.keyB 
       and sometimesupdate is not null) = 0 
    then now() 
  else sometimesupdate end)
where keyA = 100 and keyB = 200

or if you want to update that specific row which has no sometimesupdate and is keyb = 200 then do below 或者如果你想更新那个没有有时更新并且keyb = 200的特定行,那么在下面做

UPDATE mytable
SET alwaysupdate = now(),
    sometimesupdate = (CASE
      WHEN keyB = 200 THEN CASE
          WHEN sometimesupdate IS NULL THEN now()
          ELSE sometimesupdate
        END
      ELSE sometimesupdate
    END)
WHERE keyA = 100
AND keyB = 200

One method puts the logic in the from clause: 一种方法将逻辑放在from子句中:

update mytable
    set alwaysupdate = now(),
        sometimesupdate = (case when b.cnt = 0 then now() else sometimesupdate end)
    from (select count(*) from mytable where keyB = 200 and sometimesupdate is not null
         ) b
    where keyA = 100 and keyB = 200;

However, not exists would usually have better performance: 但是, not exists通常会有更好的性能:

update mytable
    set alwaysupdate = now(),
        sometimesupdate = (case when not exists (select 1 from mytable where keyB = 200 and sometimesupdate is not null)
                                then now()
                           end)
         ) b
    where keyA = 100 and keyB = 200;

You can use a chained CTE, and make the second update conditional on an EXISTS(...) [NOT EXISTS() is the same as COUNT()==zero] 您可以使用链式CTE,并使第二次更新以EXISTS(...)条件EXISTS(...) [NOT EXISTS()与COUNT()== 0]相同


  -- Run no matter what, updating 'alwaysupdate'
WITH u1 AS ( 
        UPDATE mytable 
        SET alwaysupdate = now() 
        WHERE keyA = 100 AND keyB = 200;
        RETURNING *
        )
UPDATE mytable u2
SET sometimesupdate = now() 
FROM u1
WHERE u1.keyA = u2.keyA -- 100
  AND u1.keyB = u2.keyB -- 200
        -- If 'sometimesupdate' is null for all rows below, give it a value in this row
        -- Check if there are any rows where 'sometimesupdate' has a value
AND NOT EXISTS (SELECT * 
        FROM mytable nx
        WHERE nx.keyB = u2.keyB -- 200
        AND sometimesupdate IS NOT NULL
        );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM