GROUP BY in UPDATE FROM clause - postgresql

I really need do something like that:
UPDATE table t1
SET column1=t2.column1
FROM table t2
INNER JOIN table t3
USING (column2)
GROUP BY t1.column2;
But postgres is saying that I have syntax error about GROUP BY clause. What is a different way to do this?

The UPDATE statement does not support GROUP BY, see the documentation. If you're trying to update t1 with the corresponding row from t2, you'd want to use the WHERE clause something like this:
UPDATE table t1 SET column1=t2.column1
FROM table t2
JOIN table t3 USING (column2)
WHERE t1.column2=t2.column2;
If you need to group the rows from t2/t3 before assigning to t1, you'd need to use a subquery something like this:
UPDATE table t1 SET column1=sq.column1
FROM (
SELECT t2.column1, column2
FROM table t2
JOIN table t3 USING (column2)
GROUP BY column2
) AS sq
WHERE t1.column2=sq.column2;
Although as formulated that won't work because t2.column1 isn't included in the GROUP BY statement (it would have to be an aggregate function rather than a simple column reference).
Otherwise, what exactly are you trying to do here?

In MariaDB/ MySQL this SQL work :
UPDATE table t1 left join (
SELECT t2.column1, column2
FROM table t2
JOIN table t3 USING (column2)
GROUP BY column2
) AS sq on t1.column2=sq.column2
SET column1=sq.column1;

Related

How to write a Postgres SELECT FOR UPDATE when using the EXCEPT set operator?

In Postgres (11, if it matters), I need to do a SELECT FOR UPDATE to obtain a collection of rows that I'll subsequently be doing some alterations on, and which I don't want anyone outside my transaction messing with while I do those alterations.
However, the set of rows I want to lock is actually defined by a set-difference, i.e.,
SELECT <columns> FROM table1 t1 JOIN table2 t2 ON ... WHERE ...
EXCEPT
SELECT <columns> FROM table1 t1 JOIN table3 t3 ON ... WHERE ...
I want the result-set of this set-difference to determine the set of rows that get locked; that is, those rows that are selected by the second SELECT should ideally not get locked.
But I'm not quite sure where to put the FOR UPDATE clause to achieve this. It seems like putting the FOR UPDATE immediately after either of the SELECT lines above would not give me what I want. And in fact I suspect that I can't legally put it after the first of those SELECT lines (i.e., just before the EXCEPT).
One idea that occurred to me was to parenthesize the second SELECT (the one that's the subject of the EXCEPT), so that the FOR UPDATE won't be interpreted as part of that second SELECT:
SELECT <columns> FROM table1 t1 JOIN table2 t2 ON ... WHERE ...
EXCEPT
(SELECT <columns> FROM table1 t1 JOIN table3 t3 ON ... WHERE ...)
FOR UPDATE
But I'm not sure that that gives me what I want either, even if it turns out to be syntactically acceptable.
It's possible that if I had an idea of the shape of the parse tree for a (Postgres) select statement, I could easily figure this out myself; but as it is, I'm a bit lost right now.
You cannot use FOR UPDATE together with UNION, INTERSECT or EXCEPT, because this could cause ambiguities in the general case.
I can think of two approaches:
Use EXISTS and NOT EXISTS:
SELECT ... FROM table1
WHERE EXISTS (SELECT 1 FROM table2 ...
WHERE table2.x = table1.x AND ...)
AND NOT EXISTS (SELECT 1 FROM table3 ...
WHERE table3.y = table1.y AND ...)
FOR UPDATE OF table1;
Use a subquery:
SELECT ... FROM table1
WHERE id IN (SELECT t1.id
FROM table1 t1 JOIN table2 t2 ON ...
WHERE ...
EXCEPT
SELECT t1.id
FROM table1 t1 JOIN table3 t3 ON ...
WHERE ...)
FOR UPDATE OF table1;

How to update joined table using condition

I'm having an issue with a simple update statement. I'm new to postgresql and I'm still stuck on MS Sql Server syntax.
What I want to do is to update all records from table1 which are not present / don't exist in table2. Table1 and Table2 are having an 1 to 1 relation. The join column is "colx" from my example
On Ms SQL Server I would have something like this:
UPDATE table1 set col1='some value' from table1 t1 LEFT JOIN table2 t2 on t1.colx=t2.colx WHERE t2.colx IS NULL
or
UPDATE table1 set col1='some value' from table1 t1 where not exists (select 1 from table2 t2 where t1.colx=t2.colx)
My issue is when performing the same on PostgreSql it updates all records from table1, not only the records matching the condition (e.g. I was expecting 4 records to be updated, but all records from table1 are updated instead).
I checked using a select statement the join condition for all possible approaches and I have the expected result (e.g. 4 records).
Is there anything I'm missing?
Your question is not very clear about the requirement.
What I understood is you want to update the value of col1 in table1 for those records which are not present in the table2.
You can try it this way in Postgresql:
UPDATE table1 t1 set col1='some value' where not exists(select 1 from table2 where colx=t1.colx)
DEMO

Get an Empty Column from a table when filter condition fetches empty in PostgreSQL

I have two tables table1(id,name,type) and table2(id,source,destination)
When I run query
SELECT
name,
source,
destination
FROM
table1,
table2
WHERE
table1.id=table2.id
If there's no id matching between two tables, can I still get empty column for source and destination .
Yes, you basically want an OUTER JOIN and remember to always use the explicit ANSI JOIN syntax and not the implicit comma syntax for joins.Also use proper table aliases to avoid ambiguity.
SELECT
t1.name,
t2.source,
t2.destination
FROM
table1 t1 left outer join
table2 t2 ON t1.id = t2.id

Dynamic values to another SQL statement

Is there a way to combine two SQL queries into a single SELECT query in PostgreSQL?
My requirements are as follows:
SELECT id FROM table1;
SELECT name FROM table2 WHERE table2.id = table1.id;
I think I need to pass values of table1.id in as some sort of dynamic values (loop values) for use in the SELECT statement executed on table2. What is the easiest way to solve this problem, is it possible to do this with stored procedures or functions in PostgreSQL?
select t1.id, name
from
table1 t1
inner join
table2 t2 using (id)
where t1.id = 1

How to select distinct-columns along with one nondistinct-column in DB2?

I need to perform distinct select on few columns out of which, one column is non-distinct. Can I specify which columns make up the distinct group in my SQL statement.
Currently I am doing this.
Select distinct a,b,c,d from TABLE_1 inner join TABLE_2 on TABLE_1.a = TABLE_2.a where TABLE_2.d IS NOT NULL;
The problem I have is I am getting 2 rows for the above SQL because column D holds different values. How can I form a distinct group of columns (a,b&c) ignoring column d, but have column d in my select clause as well?
FYI: I am using DB2
Thanks
Sandeep
SELECT a,b,c,MAX(d)
FROM table_1
INNER JOIN table_2 ON table_1.a = table_2.a
GROUP BY a,b,c
Well, your question, even with refinements, is still pretty general. So, you get a general answer.
Without knowing more about your table structure or your desired results, it may be impossible to give a meaningful answer, but here goes:
SELECT a, b, c, d
FROM table_1 as t1
JOIN table_2 as t2
ON t2.a = t1.a
AND t2.[some_timestamp_column] = (SELECT MAX(t3.[some_timestamp_column])
FROM table_2 as t3
WHERE t3.a = t2.a)
This assumes that table_1 is populated with single rows to retrieve, and that the one-to-many relationship between table_1 and table_2 is created because of different values of d, populated at unique [some_timestamp_column] times. If this is the case, it will get the most-recent table_2 record that matches to table_1.