Updating a table based on similar table with same structure - sql

I have test table(1) with following values
Yet I have an update of this table called table(2) :
As you can see table(2) is similar table(1) but it has new values with new dates for each ID.
How should I use update command to update table1 based on new values of table2

In sql the fastest way to do so via a merge function, it will add the new rows to the table1 that are existing in table2 and not in table1.
merge into table1 t1
using table2 t2
on t1.id = t2.id
and t1.date = t2.date
when not matched then
insert (t1.id, t1.date, t1.value1, t1.value2 , t1.value3, t1.value4)
values (t2.id, t2.date, t2.value1, t2.value2 , t2.value3, t2.value4)

What I understood from your question is that you have multiple records for each id in table2 and you want the values against the latest row based on the data to be updated to table1. in such a case, you can try with a ROW_NUMBER or RANK function, just like this
;WITH CTE
AS
(
SELECT
RN = ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Date DESC),
id,
date,
val1,
val2,
val3
FROM Table2
)
UPDATE T1
SET
Val1 = T2.Val1
Val2 = T2.Val2
FROM Table1 T1
INNER JOIN CTE T2
ON T1.id = T2.id
WHERE T2.RN = 1

Related

How to update multiple columns in the oracle SQL on ATP fusion DB

I am trying to use the below query, its everytime saying cannot insert null for the second column.
UPDATE TABLE1
SET (COL1,COL2,COL3) = (SELECT COL1,COL2,COL3
FROM TABLE2
WHERE t1.id = t2.id);
Try this:
UPDATE TABLE1 SET (COL1,COL2,COL3) =
(SELECT COL1,NVL(COL2,0),COL3 FROM TABLE1 T1, TABLE2 T2 where t1.id = t2.id)
WHERE <YOUR WHERE CONDITION>
I would use a MERGE:
MERGE INTO TABLE1 t1
USING (SELECT id, COL1,COL2,COL3
FROM TABLE2) t2
ON (t1.id = t2.id)
WHEN MATCHED THEN UPDATE SET t1.COL1 = t2.COL1
, t1.COL2 = t2.COL2
, t1.COL3 = t2.COL3;
There are rows in table1 where not corresponding row exists in table2 thus the sub-query returns nothing which means the UPDATE statement will take that as null for all three columns.
You have to add a WHERE clause that only updates rows in table1 that do have a matching row in table2
UPDATE TABLE1
SET (COL1,COL2,COL3) = (SELECT COL1,COL2,COL3
FROM TABLE2 t2
WHERE table1.id = t2.id)
where exist (select *
from table2 t2
where table1.id = t2.id);

How do I only import unique records into a table from another table?

I am trying to update a table in SQL Server. Table is called table1 with columns(code, desc). I want to update table1 with unique records from table2(code, desc). table2 is a copy of table1 but it contains records that are not present in table1.
EDIT 1: table1 consists of all the records in our ERP when exported in July, table2 consists of all the records in our ERP when exported in November (including records added after July which are the records that I want to add to table1)
To update table1.desc with values from matching rows in table2 simply do:
update t1 set
t1.desc = t2.desc
from table1 t1
join table2 t2 on t2.code = t1.code;
If however you want to insert rows into table1 that only exist in table2 (it's not exactly clear if that's the case) you can use not exists
insert into table1 (code, desc)
select code, desc
from table2 t2
where not exists (select * from table1 t1 where t1.code = t2.code);
Sounds like you want an INSERT
Something like this should work:
INSERT INTO table1 (code, desc)
SELECT t2.code, t2.desc
FROM table2 t2
LEFT JOIN table1 t1 on t2.code = t1.code and t1.desc = t2.desc
WHERE t1.code is null --Ignore records that already exist in table1
... Adjust join clause accordingly.

Update row in a table based on multiple rows in another table

I have two tables: table1 and table2:
table1 has columns id and integer
table2 has columns id and boolean
table2 can have multiple rows with the same id
I want to update the integer column of table1 by looking at all rows with the same id in table2 and seeing if any of the boolean values are true. If so I want table1.integer to be 1, else I want it to be 0.
I have tried something like this:
UPDATE table1,
(
SELECT table2.id, Sum(table2.boolean) > 0
) AS 'condition'
from table2
WHERE 1
GROUP BY table2.id) table3
SET table1.integer =IF(table3.condition, 1, 0) where table1.id = table3.id
And it seems to work, but I wanted to ask if there is a nicer/cleaner/more succinct way of updating the rows of table1 according to multiple rows of table2.
I would recommend EXISTS:
UPDATE table1 t1
SET t1.integer = (EXISTS (SELECT 1
FROM table2 t2
WHERE t2.id = t.id AND
t2.boolean
)
);
This can take advantage of an index on table2(id, boolean). With such an index, it should be faster than an approach that uses JOIN and AGGREGATION.
The syntax of your query is MySql like, so you can do a join like this:
UPDATE table1 t1 INNER JOIN (
SELECT id, MAX(boolean) maxboolean
FROM table2
GROUP BY id
) t2 ON t2.id = t1.id
SET t1.integer = t2.maxboolean
If there are ids in table1 without a corresponding id in table2 and you want the integer column for them to be updated to 0 then use a LEFT join:
UPDATE table1 t1 LEFT JOIN (
SELECT id, MAX(boolean) maxboolean
FROM table2
GROUP BY id
) t2 ON t2.id = t1.id
SET t1.integer = COALESCE(t2.maxboolean, 0)

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

Oracle SQL: Update a table with data from another table

Table 1:
id name desc
-----------------------
1 a abc
2 b def
3 c adf
Table 2:
id name desc
-----------------------
1 x 123
2 y 345
In oracle SQL, how do I run an sql update query that can update Table 1 with Table 2's name and desc using the same id? So the end result I would get is
Table 1:
id name desc
-----------------------
1 x 123
2 y 345
3 c adf
Question is taken from update one table with data from another, but specifically for oracle SQL.
This is called a correlated update
UPDATE table1 t1
SET (name, desc) = (SELECT t2.name, t2.desc
FROM table2 t2
WHERE t1.id = t2.id)
WHERE EXISTS (
SELECT 1
FROM table2 t2
WHERE t1.id = t2.id )
Assuming the join results in a key-preserved view, you could also
UPDATE (SELECT t1.id,
t1.name name1,
t1.desc desc1,
t2.name name2,
t2.desc desc2
FROM table1 t1,
table2 t2
WHERE t1.id = t2.id)
SET name1 = name2,
desc1 = desc2
Try this:
MERGE INTO table1 t1
USING
(
-- For more complicated queries you can use WITH clause here
SELECT * FROM table2
)t2
ON(t1.id = t2.id)
WHEN MATCHED THEN UPDATE SET
t1.name = t2.name,
t1.desc = t2.desc;
try
UPDATE Table1 T1 SET
T1.name = (SELECT T2.name FROM Table2 T2 WHERE T2.id = T1.id),
T1.desc = (SELECT T2.desc FROM Table2 T2 WHERE T2.id = T1.id)
WHERE T1.id IN (SELECT T2.id FROM Table2 T2 WHERE T2.id = T1.id);
Update table set column = (select...)
never worked for me since set only expects 1 value - SQL Error: ORA-01427: single-row subquery returns more than one row.
here's the solution:
BEGIN
For i in (select id, name, desc from table1)
LOOP
Update table2 set name = i.name, desc = i.desc where id = i.id;
END LOOP;
END;
That's how exactly you run it on SQLDeveloper worksheet. They say it's slow but that's the only solution that worked for me on this case.
Here seems to be an even better answer with 'in' clause that allows for multiple keys for the join:
update fp_active set STATE='E',
LAST_DATE_MAJ = sysdate where (client,code) in (select (client,code) from fp_detail
where valid = 1) ...
The full example is here:
http://forums.devshed.com/oracle-development-96/how-to-update-from-two-tables-195893.html - from web archive since link was dead.
The beef is in having the columns that you want to use as the key in parentheses in the where clause before 'in' and have the select statement with the same column names in parentheses.
where (column1,column2) in ( select (column1,column2) from table where "the set I want" );
BEGIN
For i in (select id, name, desc from table2)
LOOP
Update table1 set name = i.name, desc = i.desc where id = i.id and (name is null or desc is null);
END LOOP;
END;
If your table t1 and it's backup t2 have many columns, here's a compact way to do it.
In addition, my related problem was that only some of the columns were modified and many rows had no edits to these columns, so I wanted to leave those alone - basically restore a subset of columns from a backup of the entire table. If you want to just restore all rows, skip the where clause.
Of course the simpler way would be to delete and insert as select, but in my case I needed a solution with just updates.
The trick is that when you do select * from a pair of tables with duplicate column names, the 2nd one will get named _1. So here's what I came up with:
update (
select * from t1 join t2 on t2.id = t1.id
where id in (
select id from (
select id, col1, col2, ... from t2
minus select id, col1, col2, ... from t1
)
)
) set col1=col1_1, col2=col2_1, ...