With MySQL, I perform a delete with a join as follows:
DELETE t1
FROM t1
LEFT OUTER JOIN t2 ON t2.fk_id = t1.id
WHERE t2.id IS NULL;
Before executing the query, I would typical make sure I am okay with the outcome first by viewing the soon to be deleted records as follows:
SELECT t1.*
FROM t1
LEFT OUTER JOIN t2 ON t2.fk_id=t1.id
WHERE t2.id IS NULL;
Using PostgreSQL, I believe I should perform the same delete action as follows (EDIT below):
DELETE FROM t1
USING t2
WHERE t1.id = t2.fk_id
AND t2.id IS NULL;
Concerned that I might not be correct, I unsuccessfully tried the following:
SELECT t1.*
USING t2
WHERE t2.fk_id=t1.id
AND t2.id IS NULL;
Is there a way with PostgreSQL to perform a SELECT query using the same structure as a DELETE query?
EDIT - Not even correct since I am effectively performing an INNER JOIN and will not delete any records, and will need to change it as follows. Still would appreciate an answer to my original question.
DELETE FROM t1
USING t1 t_1
LEFT OUTER JOIN t2 ON t2.fk_id=t_1.id
WHERE t1.id=t_1.id AND t2.id IS NULL;
I would use a NOT EXISTS condition:
delete from t1
where not exists (select *
from t2
where t1.id = t2.fk_id);
That's typically faster than a join and it's also standard compliant SQL.
Related
I am trying to run a postgresql query in which I need to join three tables as part of update query but it is giving me error on join.
UPDATE table1
join table2 on (table1.id=table2.id1)
join table3 on (table2.id2=table3.id)
SET table1.name='Test',
table3.equipment_code='ABC'
WHERE table1.id='21003';
Can you please guide me accordingly?
Not tested but something like this:
UPDATE table1
SET table1.name='Test'
FROM
table1 join table2 on table1.id=table2.id1
table2 join table3 on table2.id2=table3.id
WHERE
table3.equipment_code='ABC'
AND
table1.id='21003';
Though I am not sure why you are not just doing:
UPDATE table1
SET table1.name='Test'
WHERE
table1.id='21003';
I don't see that table2 and table3 are contributing anything to the UPDATE.
you can only update one table per update query.
so what you need is two separate queries like this:
1- update table3 using table1
UPDATE table3 SET equipment_code = t.whatever
FROM (SELECT * FROM table1 JOIN table2 ON table1.id = table2.id1) AS t
WHERE t.id2 = table3.id AND table1.id = '21003';
2- then update your table1
UPDATE table1 SET name = 'Test' WHERE id = '21003';
btw if you wanna know more about the update-join syntax visit here: https://www.postgresqltutorial.com/postgresql-update-join/
I have the following SQL code:
select t1.*
from t1
join t3 on t3.id = t1.id
join t2 on t1.num = t2.num and coalesce(t1.date,t3.date) >= t2.date
but this script is not optimal at all, probably because of inequality in join.Is there a way to rewrite this, nothing comes to my mind
you can add indexes to columns t1.id, t3.id, t1.num, t2.num,
t1.date, t2.date, t3.date to perform an index scan while query
execution.
Postgresql - Index optimization for Date columns
Alternatively, if exists, also add the Direct join condition between
t2 & t3.
Use specific columns to be returned instead of "*".
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;
I frequently use below JOIN and UPDATE to bring value from one table to another in TSQL.
UPDATE T1
SET T1.Mobile = T2.Mobile
FROM Table1 T1 INNER JOIN Table2 T2 ON T1.ID = T2.ID
Then I found in PL SQL, the syntax to do such update is either by using a MERGE, or a nest statement.
Either way appear to be not as straight forward as the TSQL solution, which makes me wondering if PL SQL developer actually perform such cross table update, or if there is other development principle making such update unnecessary.
One comment I got from a PL SQL developer is that they'd rather create a view like
CREATE VIEW MyView AS
(
SELECT T1.Filed1, T1.Field2, T2.Mobile
FROM Table1 T1 INNER JOIN Table2 T2 ON T1.ID = T2.ID
);
This looks like a viable solution taking the fact that joining does not introduce duplicates into Table1/MyView, or putting a dedup logic above.
One obvious benefit for this is that we can continue refreshing Table2.Mobile, and MyView will always have the updated value.
I am seeking comment on coding principle. :)
You may update using a correlated subquery:
UPDATE Table1 T1
SET T1.Mobile = (SELECT Mobile FROM Table2 T2 WHERE T1.ID = T2.ID);
You should use this query to make an inner join.
Without the where clause it's just a left join, that can consists of empty mobile data from T2
UPDATE Table1 T1
SET T1.Mobile = (SELECT min(Mobile) FROM Table2 T2 WHERE T1.ID = T2.ID)
where T1.ID in (SELECT T2.ID FROM Table2 T2)
;
And with the max(Mobile) you prevent to get an error when you have a
1:n relation for T1:T2.
To speedup the statements you should create indexes on T1.ID and T2.ID
Is there any difference/limitations/considerations that need to be made when adding additional criteria to a JOIN rather than including it in a WHERE clause. Example...
SELECT
*
FROM
TABLE1 t1
INNER JOIN
TABLE2 t2
ON t1.a = t2.a
AND
t1.DATE_TIME < 06/01/2015
versus
SELECT
*
FROM
TABLE1 t1
INNER JOIN
TABLE2 t2
ON t1.a = t2.a
WHERE
t1.DATE_TIME < 06/01/2015
All the optimizers of DBMS threats the two queries in the same way, so there is no difference in performance between them. The most commonly used form is the second one.
The optimize most likely will treat those two the same
But if you get into 4 or more join what can happen is for the query optimizer to go into a loop join and in that case they might process differently
The safer bet is to have the condition in the join (the first)