Can I construct an update query in postgres where the columns to update are nested in a case? - postgresql

Is there a way in postgres to update multiple columns with a single case clause? I've only ever seen it done the other way around--that is, multiple case clauses for each column:
update table
set col1 = case when condition then value1 else value2 end
set col2 = case when condition then value3 else value4 end
where ...
But what if I want to update several columns and the condition in the case clause is the same for all of them? Wouldn't it be more consise to have a syntax that allows the case clause to be written once and each column nested inside it? Something like this:
update table
case when condition then
set col1 = value1, col2 = value2, ...
else
set col1 = value3, col2 = value4, ...
end
where ...
Is this possible in postgres?

Related

How to update table based on CASE logic?

I need to update a table based on a value derived from case logic. That case logic is created using several other tables, such as this:
CASE
WHEN column = 'value'
THEN
COALESCE
(
CASE WHEN column = 'test1' THEN 'result' END,
CASE WHEN column = 'test2' THEN 'result' END
)
ELSE
column
END AS Derived_Column
FROM
table_a a
LEFT JOIN table_b b ON a.column = b.column
LEFT JOIN tabel_c c ON b.column = c.column
What I need to to do something like this:
UPDATE table SET column =
( SELECT column FROM table WHERE column = <CASE STATEMENT LOGIC>)
Somehow I need to updated the column in the table filtering on the the output of Derived_Column. So I need to check against a sub query or something of that nature.
Would anyone know how to do this?

Detect not contemplated values in a CASE statement evaluation

Is there a way in T-SQL to collect all not contemplated values in a CASE condition and insert them in a table?
For example:
A SELECT that reads a table that has in Col1 the values A,B,C. This SELECT has a CASE that goes like this: CASE WHEN Col1 = 1 THEN ... WHEN Col1 = B THEN ... ELSE NULL END AS NewCol1
I would like to detect values like C, values that are not contemplated in Col1.
I could get them like this: (...) ELSE Tabl1.Col1 but I need the CASE statement to end with ELSE NULL.
You can get a list of these values like this:
SELECT DISTINCT Col1
FROM Table
WHERE Col1 not in (1,...,B)
As #avery_larry suggested, I used a debug flag, giving my query two behaviours. I could call a function/stored with the parameter and if it's up INSERT the values into a desired output.

Update multiple columns based on other columns in same table

I'm trying to update two columns certain values based on two other columns, with certain values in the same table, but they keep coming up with something called bind.
This is what doesn't work:
UPDATE table t1
SET t1.column1 = value1, t1.column2 = value2
WHERE t1.column5 = cake
AND t1.column7 = pie;
I assume you are getting an "invalid identifier" error, if my assumption is correct then the only possible mistake in your code is you forgot to enclose your values in single qoutation marks.
UPDATE table t1
SET t1.column1 = value1, t1.column2 = value2
WHERE t1.column5 = 'cake'
AND t1.column7 = 'pie';
Note that if you are assigning/comparing a value with a datatype string, you should always enclose it with single-qoutation marks.

Conditional index in PostgreSQL

I know from using Oracle that conditonal index with CASE statement is possible. But is it possible in PostgreSQL? For example index is following:
CREATE INDEX IX_INDEXNAME ON SOME_TABLE (
CASE
WHEN COLUMN1 = 0 AND COLUMN2 = 'value' THEN SOME1_ID
ELSE SOME2_ID
END);
This is already modified version for PostgreSQL, because Oracle case statement is different from Postgres. If this is possbile how do I do that? Or if this is not possible, is there another way to realize it?
You need to enclose the CASE expression in parentheses:
CREATE INDEX IX_INDEXNAME ON SOME_TABLE (
(CASE
WHEN COLUMN1 = 0 AND COLUMN2 = 'value' THEN SOME1_ID
ELSE SOME2_ID
END) );

PostgreSQL Conditional selects

I have written a recursive function and depending on the output I need to select different fields. My question is now, how can I do this multiple times without having to call the function more then once? What I'm doing right now is just using the CASE WHEN... condition and checking every time what the functions return. (This is only a pseudo code and doesn't do anything real, it's just for understanding)
SELECT
id,
(CASE WHEN (function(id) > 0)
THEN field1
ELSE field2
END) as value1,
(CASE WHEN (function(id) > 0)
THEN field3
ELSE field4
END) as value2,
(CASE WHEN (function(id) > 0)
THEN field5
ELSE field6
END) as value3
FROM table1
...
How can I optimize this query and call the function only once?
Thanks in advance!
If the function is declared IMMUTABLE, it is safe to call it many times, as it will not be reevaluated.
From the docs:
IMMUTABLE indicates that the function cannot modify the database and always returns the same result when given the same argument values; that is, it does not do database lookups or otherwise use information not directly present in its argument list. If this option is given, any call of the function with all-constant arguments can be immediately replaced with the function value.
use a subquery :
SELECT foo, bar, result
FROM (
SELECT ..., function(id) AS result
....
) as tmp
You may be able to use some funky tuple thing like:
SELECT id,
CASE WHEN function(id) > 0
THEN (field1, field3, field5)
ELSE (field2, field4, field6)
END as (value1, value2, value3)
but I have no experience with this syntax