Reputation: 9632
In Postgres 10 I want to perform an UPDATE twice. First UPDATE should run no matter what, updating the alwaysupdate
column. 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
.
-- 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? Otherwise multiple statements wrapped in a transaction? Otherwise a function if necessary.
Upvotes: 2
Views: 5337
Reputation: 4523
You can use a chained CTE, and make the second update conditional on an EXISTS(...)
[NOT EXISTS() is the same as COUNT()==zero]
-- 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
);
Upvotes: 1
Reputation: 1271151
One method puts the logic in the from
clause:
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:
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;
Upvotes: 1
Reputation: 4824
Try this
if count is equal to zero then update to now() otherwise retain the old value of sometimesupdate
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
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
Upvotes: 1