postgres update multiple columns in single query - postgresql

I want to update multiple columns in table which are conditionally dependent on each other.
create table justtable(a numeric, b numeric, c numeric,d numeric,e numeric)
insert into justtable values(1,10,10,10,10)
select * from justtable
returns - 1;10;10;10;10
update justtable set b=10, c=b*2, d=c*2, e=d*2 where a=1;
select * from justtable
returns - 1;10;20;20;20
I want it to return 1;10;20;40;80.
Is it possible to do this is single query else will have to write multiple updates in sequence. Please suggest.

In your case, I would use some arithmetic to rewrite the query, the b column is the minimum base for arithmetic, so we might get formulas like below.
c = 2 * b
d = 4 * b
e = 8 * b
you can try to use this
update justtable
set b=10, c=b*2, d=b*4, e=b*8
where a=1;
sqlfiddle

Related

Postgres WHERE clause with infinity

I have the following WHERE clause on a table x with column 1 as integer.
The SELECT is called in a function with parameters (a integer, b integer)
Call the function:
SELECT * FROM function(0, 10)
Script in funcion:
SELECT * FROM tablex x WHERE x.column1 between a and b
Now i miss the results where column1 is null, but in this case it is important to get these. Depends who calls the function. What should be parameter "a" to also get the null values. Or is there a way to disable the where clause depending on the paramter which are coming?
I found a nice solution for this:
SELECT * FROM tablex x WHERE coalesce(x.column1, 0) between a and b
Add logic to admit null column1 values:
SELECT *
FROM tablex x
WHERE x.column1 BETWEEN a AND b OR x.column1 IS NULL;
To make the NULLs behave as actual values, invert the logic.
[and add a comment to the code, because the negation might confuse future readers/maintainers]:
SELECT * FROM tablex x WHERE NOT x.column1 < a and NOT x.column1 >= b;
Note the above assumes you want NULLs in both a and b to be treated as -inf and +inf , respectively.

Query table by a value in the second dimension of a two dimensional array column

WHAT I HAVE
I have a table with the following definition:
CREATE TABLE "Highlights"
(
id uuid,
chunks numeric[][]
)
WHAT I NEED TO DO
I need to query the data in the table using the following predicate:
... WHERE id = 'some uuid' and chunks[????????][1] > 10 chunks[????????][3] < 20
What should I put instead of [????????] in order to scan all items in the first dimension of the array?
Notes
I'm not entirely sure that chunks[][1] even close to something I need.
All I need is to test a row, whether its chunks column contains a two dimensional array, that has in any of its tuples some specific values.
May be there's better alternative, but this might do - you just go over first dimension of each array and testing your condition:
select *
from highlights as h
where
exists (
select
from generate_series(1, array_length(h.chunks, 1)) as tt(i)
where
-- your condition goes here
h.chunks[tt.i][1] > 10 and h.chunks[tt.i][3] < 20
)
db<>fiddle demo
update as #arie-r pointed out, it'd be better to use generate_subscripts function:
select *
from highlights as h
where
exists (
select *
from generate_subscripts(h.chunks, 1) as tt(i)
where
h.chunks[tt.i][3] = 6
)
db<>fiddle demo

PostgreSQL doesn't update/copy boolean from subselect?

Here's a short code sample that behaves unexpectedly for me in PostgreSQL v9.5:
create table test (a boolean, b boolean);
insert into test (a) values ('true'),('true'),('true'),('true'),('true');
update test set b = rand.val from (select random() > 0.5 as val from test) as rand;
I expect column b to take on random true/false values, but for some reason it's always false. If I run the subselect of:
select random() > 0.5 as val from test;
It returns random true/false combinations as I want. But for some reason once I try to update the actual table it fails. I've tried several casting combinations but it doesn't seem to help.
What am I missing here?
How about:
update test set b = (random() > 0.5);

updating a table in tsql with multiple conditions

If I have a table MyTable with columns a,b and c, which are ints. Given that I want to update all 'a's based on the values of b and c.
Update MyTable set a = 2 where b = 1 and c = 1
It's far too late, and I cannot for the life of me see why this statement doesn't work, am I missing something silly?
Edit, woops, forgot the error.
"Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
Edit2: That was the exact query I was using (different column names). Turns out there was a trigger on the table which was broken. I feel a little silly now, but thanks for the help anyway :)
There's nothing wrong with the statement you posted. The error is elsewhere.
Could you have posted the wrong query? Or perhaps you over-simplified it? A subquery looks something like this:
UPDATE MyTable
SET a = 2
WHERE b = 1 AND c = (SELECT c FROM MyTable2 WHERE id = 5)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <--- subquery
An invalid query that could give the error message you get could look like this:
UPDATE MyTable
SET a = 2
WHERE b = 1 AND c = (SELECT c, d FROM MyTable2 WHERE id = 5)
The second query is invalid because it returns two values but the = operator only allows comparison to a single value.
The solution is to ensure that all subqueries used in equality comparisons only return a single row consisting of a single column.

How to get min/max of two integers in Postgres/SQL?

How do I find the maximum (or minimum) of two integers in Postgres/SQL? One of the integers is not a column value.
I will give an example scenario:
I would like to subtract an integer from a column (in all rows), but the result should not be less than zero. So, to begin with, I have:
UPDATE my_table
SET my_column = my_column - 10;
But this can make some of the values negative. What I would like (in pseudo code) is:
UPDATE my_table
SET my_column = MAXIMUM(my_column - 10, 0);
Have a look at GREATEST and LEAST.
UPDATE my_table
SET my_column = GREATEST(my_column - 10, 0);
You want the inline sql case:
set my_column = case when my_column - 10 > 0 then my_column - 10 else 0 end
max() is an aggregate function and gets the maximum of a row of a result set.
Edit: oops, didn't know about greatest and least in postgres. Use that instead.