PostgreSQL updating more rows than in where condition? - sql

I have the following simple SQL update:
update t2 set col = 2
from t2, t1
where t2.id = t1.id
and t1.name = 'test';
But all the rows in t2 are updated! i.e. not just the one with the id where name is 'test', how do I achieve this in Postgres?

You've got too much from from t1,t2
do this:
update t2 set col = 2
from t1
where t2.id = t1.id
and t1.name = 'test';
If you must have t2 in the from alias it and join all three tables in the where..
update t2 as t2_up set col = 2
from t2 as t2_from , t1
where t2_from.id = t1.id
and t2_up.id = t2_from.id
and t1.name = 'test';

I'm guessing that you really mean:
update t2
set col = 2
from t2 join
t1
on t1.id = t2.id
where t1.name = 'test';
The condition t1.id = t1.id doesn't really make much sense in a query. It is equivalent to t1.id is not null. Hence, all rows in t2 would get updated due to the cross join.

Related

SQL three table joins using two ids and another column

I have three tables
t1 t2 t3
I want to select data from only two of the tables but need the ids and columns from other tables for reference.
How to select data from t3 and t2
WHERE t1.id = t2.id = t3.id
AND t1.fid = t2.fid = t3.fid
AND t1.type = 'abc'
id column will be the same value for all tables. fid column will have incremental fid's but need the ones where t1.type = 'abc' also
Would this work?
select data
from t3
select data
from t2
join on t1.id = t2.id and t2.id = t3.id
join on t1.fid = t2.fid and t2.fid = t3.fid and t1.type = 'abc'
where id = 1
Generally, this kind of problem can be solved using EXISTS as follows:
select data
from t2
join t1 on t1.id = t2.id and t1.fid = t2.fid
where exists (select 1 from t3 where t2.id = t3.id and t2.fid = t3.fid)
and t1.type = 'abc'
and t1.id = 1
You could try something like this:
select columns_that_you_want
from t1 x
inner join t2 y on x.id = y.id
inner join t3 z on y.id = z.id
where x.type = 'abc'
;
This will join the three tables, and filter just the type 'abc' that you want from table t1. Also you can add more filter on the where clause in case you need to filter more the result.

Update values in one table with values in another table

I have table1 and table2. They have the same columns and the column ID is the one that i can use to connect the tables.
How can i run foreach statment that will update row Name in table1 with the value for column Name in table2?
I need this so i can fix the column Name in Table1 because it is incorect , and the good values for it are in table2
I tried using a single update statement but it takes forever to execute because both tables are with over 600 000 rows
update
table1 t1
set
(
t1.name
) = (
select
t2.name
from
table2 t2
where
t2.id = t1.id
and
rownum = 1
)
where exists (
select
null
from
table2 t2
where
t2.id = t1.id
);
For this query:
update table1 t1
set t1.name = (select t2.name from table2 t2 where t2.id = t1.id and rownum = 1)
where exists (select 1
from table2 t2
where t2.id = t1.id
);
You want an index on table2(id, name).
A simple inner join should work this.
UPDATE T1
SET T1.NAME = T2.NAME
FROM MyTable T1
INNER JOIN MyOtherTable T2
ON T1.ID = T2.ID

SQL: select from t1 all rows for which there's no corresponding in t2

Let's say I have a table t1 with only one column: id, and I have a table t2 with two columns: id and Memo. I need to select those id from t1, for which there is NO row in t2 that satisfies both of the following two conditions t1.id = t2.id and t2.Memo = 'myText'. How can I do that? I have tried using join, but that selects row that do satisfy some conditions, whereas I need the opposite.
SELECT *
FROM t1
WHERE NOT EXISTS (SELECT 1
FROM t2
WHERE t2.id = t1.id
AND t2.Memo = 'myText')
One way to do it is using LEFT JOIN:
select id
from t1
left join t2
on t1.id = t2.id and t2.Memo = 'myText'
where t2.id is null
I'm not good in understanding your question:
You mean those t1.id EXISTS in t2 BUT the corresponding t2.Memo <> 'myText'?
SELECT t1.id FROM t1 JOIN t2
ON t1.id = t2.id
HAVING t1.id NOT IN (SELECT id FROM t2 WHERE Memo = 'myText');
Or all t1.id either NOT EXISTS in t2 or EXISTS but Memo <> 'myText'?
SELECT id FROM t1 WHERE id NOT IN (SELECT id FROM t2 WHERE Memo = 'myText');

Oracle SQL correlated update low performance

I have to update table(table3) with data from two other tables.
These two tables (table1,table2) are both describing single object, therefore table1.id equals table2.id for that single object.
Table 3 is a many-to-many mapping table for that object and another one which is not important here. Into that mapping table I need to put some data from table1 and table2.
I am trying to update table3 with correlated query, but it takes a very long time to complete. I ran this query on group of ~500.000 records and it runs for over an hour now.
Am I doing something wrong here?
UPDATE table3 t3
SET (t3.some_value1, t3.other_value1, t3.some_value2, t3.other_value2) =
( SELECT t1.some_value1, t1.other_value1, t2.some_value2, t2.other_value2
FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id
WHERE t3.fk = t1.id)
WHERE EXISTS (SELECT 1 FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id WHERE t3.fk = t1.id);
SELECT * FROM table3;
SQL Fiddle
Use this:
UPDATE
(SELECT
T3.SOME_VALUE1 TARGET1,
T3.OTHER_VALUE1 TARGET2,
T3.SOME_VALUE2 TARGET3,
T3.OTHER_VALUE2 TARGET4,
T1.SOME_VALUE1 SOURCE1,
T1.OTHER_VALUE1 SOURCE2,
T2.SOME_VALUE2 SOURCE3,
T2.OTHER_VALUE2 SOURCE4
FROM
TABLE1 T1
JOIN TABLE2 T2
ON T1.ID = T2.ID
JOIN T3
ON T3.FK = T1.ID)
SET
TARGET1 = SOURCE1,
TARGET2 = SOURCE2,
TARGET3 = SOURCE3,
TARGET4 = SOURCE4;
If you face ORA-01779 cannot modify a column which maps to a non key-preserved table then try using UPDATE /*+ BYPASS_UJCV */ or add a unique index on T1.ID, T2.ID, T3.FK
The answer provided by #SriniV uses a technique called an Updatable Join View. In later versions of Oracle, this can be replaced with a MERGE:
MERGE INTO t3
USING (
SELECT t1.id
t1.some_value1,
t1.other_value1,
t2.some_value2,
t2.other_value2
FROM table1 t1
JOIN table2 t2 ON t1.id = t2.id
WHERE 1=1
AND t3.fk = t1.id
) a ON (
t3.fk = a.id
)
WHEN MATCHED THEN UPDATE
SET t3.some_value = a.some_value,
t3.other_value1 = a.other_value1
t3.some_value2 = a.some_value2
t3.other_value2 = a.other_value2

How to Update Column from a Column in another table

There are probably better ways, but this worked for me:
Update t1
set t1.ListKey = t2.ListKey
From Jet.LookupListItemEntity_Default t1
join (Select ListKey, Id from Jet.LookupListEntity_default) as t2
on t1.ListId = t2.id
Greg
Update t1
set t1.ListKey = t2.ListKey
From Jet.LookupListItemEntity_Default t1
join Jet.LookupListEntity_default t2 on t1.ListId = t2.id