Postgresql Update using Inner Join set - sql

I have two tables that they share two fields (myfield1, myfield2) and one of the two tables has 2 other fields of interest.
Here is what I want to do:
1. Inner Join the two tables
2. Update a column (field1) in Table2 with either fields (afield or anotherfield) from the other table depending on afield is null or not.
The code below runs fine but the targeted set field (field1) doesn't get updated with anything.
Update Table2
Set field1 = (
CASE
WHEN os.afield is not null
THEN (os.afield)
Else os.anotherfield
End
)
from Table1 os
inner join Table2 fd
ON fd.myfield1= os.myfield1
AND fd.myfield2 = os.myfield2;

Update Table2 fd
Set fd.field1 =
(select CASE WHEN os.afield is not null THEN (os.afield) Else os.anotherfield End
from Table1 os
where fd.myfield1= os.myfield1
AND fd.myfield2 = os.myfield2);
It's called a correlated subquery which is executed for each row in Table2. But you must be sure that subquery returns single or zero rows.
This query will update all rows in Table2 if you want to update only those rows which exist in Table1 you need a WHERE
Update Table2 fd
Set fd.field1 =
(select CASE WHEN os.afield is not null THEN (os.afield) Else os.anotherfield End
from Table1 os
where fd.myfield1= os.myfield1
AND fd.myfield2 = os.myfield2)
where exists (
select 1 from Table1 os
where fd.myfield1= os.myfield1
AND fd.myfield2 = os.myfield2);

Related

Update column in SQL table with values from another row in same table

I have a table with 5 columns (name, record, un, svun, svrecord):
Name
idrecord
un
svun
svrecord
John Doe
JD123
johndoe
NULL
JM123
Jane Doe
JaD123
janedoe
NULL
OR123
Olive Err
OR123
oliverr
NULL
GH123
I'm trying to populate the svun column with the value from the idrecord column when the svrecord matches an idrecord from another row.
For instance, row #2 should update the svun column to OR123 because the svrecord (OR123) matches the idrecord (OR123) from the table. Hope this makes sense.
I've started trying to come up with a query for this below but can't quite figure it out...I'm sure i'm missing a parameter to make this work or maybe an additional select statement...:
UPDATE table
SET svun = idrecord
WHERE (svrecord = idrecord)
First, take a look at update joins here: https://www.sqlservertutorial.net/sql-server-basics/sql-server-update-join/
You will see this example:
UPDATE
t1
SET
t1.c1 = t2.c2,
t1.c2 = expression,
...
FROM
t1
[INNER | LEFT] JOIN t2 ON join_predicate
WHERE
where_predicate;
Now, we need to apply this for your table:
UPDATE
t1
SET
t1.svun = t1.idrecord
FROM
yourtable t1
JOIN
yourtable t2
ON
t1.svrecord = t2.idrecort
Your initial query will only update svun = idrecord where svrecord = idrecord in the same row.
UPDATE table SET svun = idrecord WHERE (svrecord = idrecord)
In order to update records based on values that match in different rows you'll have to use a self join
with new_results as (
select a.Name, a.svun, a.idrecord
from table a
inner join table b
where a.svrecord = b.idrecord
)
update new_results set svun = idrecord where svun is null
I don't recommend running this code without testing, but this should get you started
Update table1
SET table1.svun = table2.idrecord
FROM table table1
INNER JOIN table table2
ON table1.svrecord = table2.idrecord
You could join the table to itself.
UPDATE YourTable
SET a.svun = b.idrecord
FROM YourTable a
INNER JOIN YourTable b
ON a.svrecord = b.idrecord

How do I insert values into a new table using SQL WHERE clause for matching?

I have two tables: Table 1 is the master table and Table 2 is a table that is refreshed monthly and truncated after. Thus, I want to write a query that inserts monthly new values from Table 2 into Table 1 using some matching fields. The columns I need to match by are country and name. Here are the tables:
How do I approach this query to get to the green table? I looked into Update and Insert Statements but could not find anything which could help.
How about using MERGE statement
MERGE INTO Table1 as Target
USING Table2 as Source
ON (target.Name = source.Name AND target.Country = source.Country)
WHEN MATCHED THEN UPDATE SET Age = source.Age, Gender = source.Gender
WHEN NOT MATCHED THEN INSERT (Name, Country, Age, Gender) VALUES (source.Name, source.Country, source.Age, source.Gender);
What the statment does is look for records in Target that match records in source by name and country. If a Match is found, the Age and Gender of the target records are update, when a match is not found, a new record is inserted in target table.
I tested this in SQL Server, but I think snowflake has the same syntax.
You can read about MERGE statement in Snowflake documentation.
Snowflake syntax
UPDATE
table1 AS TA
SET
TA.Age = TB.Age
FROM (SELECT TA1.country, TB1.country, TA1.name, TB1.name, TB1.Age
FROM table1 AS TA1
INNER JOIN table2 AS TB1
ON (TA1.country = TB1.country AND TA1.name= TB1.name)) TB
WHERE TA.country = TB.country
And MySql
UPDATE
table1 AS TA
INNER JOIN table2 AS TB
ON TA.country = TB.country
AND TA.name= TB.name
SET
TA.Age = TB.Age;
Considering you have to only update the age column in the table1.
update table1 set AGE=(select distinct age from table2 t2 where t2.COUNTRY=table1.COUNTRY and t2.NAME=table1.NAME);
or
UPDATE table1 SET table1.age = table2.age FROM table1 , table2 where table1.country = table2.country and table1.name = table2.name
Snowflake syntax is a bit different here. Something like this should work:
UPDATE table1 TA
SET TA.Age = TB.Age
FROM table2 TB
WHERE TA.country = TB.country
AND TA.name = TB.name;
As a note, the documentation on Snowflake is excellent. The syntax for this is located here: https://docs.snowflake.com/en/sql-reference/sql/update.html

Multiple SET in single UPDATE statement?

I'm working on SQL Server, Oracle, DB2 Database.
Currently, I'm performing the below 2 update statement to update one table.
Update 1:
UPDATE TABLE1
SET COL1=TABLE2.ATTRIBUTE1,
COL2=TABLE2.ATTRIBUTE2,
COL3=TABLE2.ATTRIBUTE3
FROM TABLE1
INNER JOIN TABLE2
ON COL1=TABLE2.PID1
AND COL2=TABLE2.PID2
WHERE ROWNUM<10
Update 2:
UPDATE TABLE1
SET COL1=’123-4567890-1’,
COL2=’0000000000’,
COL3=’CONSTANT FULL NAME’
WHERE NOT EXISTS (SELECT 1 FROM TABLE2 WHERE COL1=TABLE2.PID1)
Update 1, helps to updates the TABLE1 if the values match with Table2 and
Update 2, helps to update the TABLE1 if the values, not match with Table2
Is there any other way to convert two update statement into single UPDATE statement?
NOTE: We can use MERGE also, but MERGE will update if the data matched and will insert if the data not matched.
To have one update, you can use two LEFT JOINs, one for each table join condition. And then, in SET part, you use CASE WHEN ... THEN ... END checking if the PK from related joins IS NULL.
Something like below
UPDATE TABLE1
SET COL1=CASE
WHEN T1.PID1 IS NOT NULL THEN T1.ATTRIBUTE1
WHEN T2.PID1 IS NULL THEN ’123-4567890-1’
ELSE COL1
END,
etc.
FROM TABLE1
LEFT JOIN TABLE2 T1 ON COL1=T1.PID1 AND COL2=T1.PID2 AND ROWNUM < 10
LEFT JOIN TABLE2 T2 ON CEDULA=T2.PID1
WHERE T2.PID1 IS NULL OR T1.PID1 IS NOT NULL
However, having one UPDATE statement doesn't mean it will be faster - check the query plan and actual performance.

Two different update statements - Only one working

I have two different variations of update statements for a stored procedure. The top one does not work and the bottom one does.
Could any of you please provide insight as to why it doesn't?
UPDATE table1
SET outcome = (
SELECT outcome
FROM table2
WHERE table1.StatusID = table2.StatusID
AND table1.IDUser = table2.UserID
)
The one below works, even though I have exactly the same constraints.
UPDATE a
SET a.outcome = b.outcome
FROM table1 A
INNER JOIN table2 B ON A.IDUser = B.UserID AND A.StatusID = B.StatusID
The first update will fail, when there are more rows in table2 matching the join. The second update will pick an arbitrary value for outcome from the join and use that value in the update.
This change to the first update should work, or rather give the same result:
UPDATE table1
SET outcome = (
SELECT TOP 1 outcome
FROM table2
WHERE table1.StatusID = table2.StatusID
AND table1.IDUser = table2.UserID
)
Maybe this would be better than your existing update. This way you will have some control of which value will end up in outcome in table1:
UPDATE table1
SET outcome = (
SELECT MAX(outcome)
FROM table2
WHERE table1.StatusID = table2.StatusID
AND table1.IDUser = table2.UserID
)
It is normal that first query does not work the way you want because it is a wrong query.
Your first code has a main query and a sub query.
In your subquery, you join the tables and get a result set.
But in your main query, you set your every row with the returned result from sub query, since you have no where block. There should be a null value in that result set. This is the reason of you having null after update.
You must do the joining out of your subquery, exactly like you do in the second code.
UPDATE table1
SET outcome = (
SELECT TOP(1)outcome
FROM table2
WHERE table2.StatusID = table1.StatusID
AND table2.IDUser = table1.IDUser
)

Can't update from NULL to 0

Hi i'm using this command to left join a table with another table that has a little more records but it keep printing NULL. I want that NULL to become 0.
SELECT * FROM TABLE1
Left JOIN Table2 ON TABLE1.ID=Table2.IDRel
UPDATE Table2 SET IDRel = 0 where IDRel = NULL
The update should not be needed.
As you said Table2 has a little more records that's the key thing here, that means that for any row from Table1 for which no matching IDRel value could be found that column (IDRel) will stay NULL.
Now you could for example use ISNULL(IDRel, 0) to replace null value with 0, but maybe an INNER JOIN instead of the LEFT JOIN could get you the right result throwing out all rows that could not be matched...
However... If you really were to update that column it would only work if you did the correct comparison against NULL (that is IS not =) that would mean changing your update query into:
UPDATE Table2 SET IDRel = 0 where IDRel IS NULL
IS the update even needed?
SELECT T1.*, coalesce(t2.IDREL,0) as IDREL
FROM TABLE1 T1
Left JOIN Table2 ON TABLE1.ID=Table2.IDRel
Use this query
UPDATE Table2 SET IDRel = 0 where IDRel is NULL
use IS NUll
SELECT * FROM TABLE1
Left JOIN Table2 ON TABLE1.ID=Table2.IDRel
UPDATE Table2 SET IDRel = 0 where IDRel IS NULL