join clause, match or null - sql

So I have some procs I inherited that I am trying to clean up. One of the things I see over and over in them is the following:
Update Table_A
Set A.ColX = B.Colx
From Table_A A
Join Table_B B on B.col1 =A.col1
and B.col2 = A.col2
Update Table_A
Set A.ColX = B.Colx
From Table_A A
Join Table_B B on a.col1 =b.col1
and B.col2 is null
Now , I have tried to combine these to make them a single query using the following different final lines (not at the same time!):
1) and (B.col2 = A.col2 or B.col2 is null)
2) and (isnull(B.col2,'') = COALESCE(a.col2, ''))
However, it always seems to do one of the updates, not both. I feel like I am missing something rather obvious, Is there a good way to combine these two queries?
thanks

This query should work:
Update Table_A
Set A.ColX = B.Colx
From Table_A A
Join Table_B B on B.col1 = A.col1
and (B.col2 = A.col2 OR or B.col2 is null)
which you said you tried - but you may try it as a SELECT first and see what the results are. That may shed some light on why you're not getting the results you expect.

I would expect the following query to work in SQL Server:
Update A
Set ColX = B.Colx
From Table_A A Join
Table_B B
on a.col1 = b.col1 and
(B.col2 = A.col2 or B.col2 is null);
Notes:
You should use the alias defined in the from clause after the update. My understanding is that if you use the table name and the table is not in the from clause without an alias, then all rows will be updated.
Although I was pretty sure that SQL Server does not support table aliases in the set, I appear to be wrong about that, as this simple SQL Fiddle shows. Perhaps this was not allowed in some ancient version of SQL Server, and the limitation just stuck with me.

Related

MSSQL How to copy data from one table to another with a condition

I'm trying to update table a with data from some of the columns in table b. Column names are matching in both tables, cannot figure out the syntax, can anyone help?
This is what I want to do (expressed out-of-syntax):
UPDATE table_a
SET table_a.col1 = table_b.col1, table_a.col2 = table_b.col2
WHERE table_a.id = table_b.id
Maybe (probably) I would need some kind of JOIN-clause, but I haven't gotten my head around those yet.... :-/
You can update your table using a JOIN of the two tables:
UPDATE table_a a
INNER JOIN table_b b ON a.id = b.id
SET a.col1 = b.col1, a.col2 = b.col2
I see you are on MYSQL. Not sure if the version above works. If not, try:
UPDATE table_a a
INNER JOIN table_b b
SET a.col1 = b.col1, a.col2 = b.col2
WHERE a.id = b.id
Ok, so I found it myself... :-)
MERGE (without using the WHEN NOT MATCHED clause)is the answer to my problem.
My solution:
MERGE INTO table_a
USING table_b
ON a.id=b.id
WHEN MATCHED THEN UPDATE SET
col1 = b.col1, col2 = b.col2;

Seeking a Teradata Merge alternative

I have an existing process where I am using a Merge statement. I now need to add additional columns in one of the tables. I added one of the new fields to Table A's primary index, but that data doesn't exist in Table B, the source of the Merge, so the Merge fails. If I remove the primary index on Table A, Merge also fails.
-- TABLEA Primary Index - COL1,COL2,COL3,COL4,COL5,COL6
-- TABLEB No Primary Index
Merge into TableA
Using TableB
on A.COL1 = B.COL1
AND A.COL2 = B.COL2
AND A.COL3 = B.COL3
AND A.COL4 = B.COL4
This produces error message: "MERGE Failed. [5758] The search condition must fully specify the Target table primary index and partition column(s) and expression must match INSERT specification primary index and partition column(s)."
If I remove the primary key from TableA I get this message: "MERGE Failed. [9252] An invalid statement was attempted on a table without a primary index: Merge-Into NoPI tables is not allowed."
So, If I can't use Merge, as TableB doesn't have some of TableA's Primary Index columns, what are my options? I'm not sure if there are other Teradata functions.
I tried this, but it didn't find the records in TableB, which are not in TableA:
SELECT B.COL1
,B.COL2
,B.COL11
,B.COL8
,B.COL9
,B.COL3
,B.COL4
,'N'
FROM TABLEB B
WHERE NOT EXISTS (SELECT 1
FROM TABLEA A
INNER JOIN TABLEB B
ON B.COL1 = A.COL1
AND B.COL2 = A.COL2
AND B.COL3 = A.COL3
AND B.COL4 = A.COL4)
There's probably no need to add another column to the existing PI, PI <> PK.
Regarding the NOT EXISTS query, it's a non-correlated subquery which results in true if there's any matching row. You need a correlated subquery:
SELECT B.COL1
,B.COL2
,B.COL11
,B.COL8
,B.COL9
,B.COL3
,B.COL4
,'N'
FROM TABLEB B
WHERE NOT EXISTS (SELECT 1
FROM TABLEA A
WHERE B.COL1 = A.COL1
AND B.COL2 = A.COL2
AND B.COL3 = A.COL3
AND B.COL4 = A.COL4)

PostgreSQL comparing null values in case statement

when I wrote a case statement to compare values in tables, it came unstuck with variables that are null. It thinks they are different (note: col1 is a character field).
select a.id,
a.col1 as a_col1,
b.col1 as b.col1,
case when a.col1=b.col1 then 0 else 1 end as chk_col1
from tablea a,
tableb b
where a.id=b.id;
... chk_col1 is always 0 when both col1's are null. I've tried
coalesce(a.col1,'null') as coalesce(b.col1,'null')
but this didn't work either. It still returned 1 for chk_col1.
Postgres supports the null-safe comparison operator is not distinct from. So, try this:
select a.id,
a.col1 as a_col1,
b.col1 as b.col1,
(case when a.col1 is not distinct from b.col1 then 0 else 1 end) as chk_col1
from tablea a join
tableb b
on a.id = b.id;
Personally, I would leave the value as a boolean:
select a.id, a.col1 as a_col1, b.col1 as b.col1,
(a.col1 is distinct from b.col1) as chk_col1
from tablea a join
tableb b
on a.id = b.id;
Also note that I used proper, explicit, standard, readable JOIN syntax.
SOLUTION! :
The variable referenced in the colaesce function must be the calculated one, i.e.
coalesce(a_col1,'null') as coalesce(b_col1,'null')
Another thing I discovered. Let's say col2 is numeric. The above doesn't work, you'd need to use a 0. Or ... more cunningly, you can use '0', i.e.
coalesce(a_col2,'0') as coalesce(b_col2,'0')
This is handy to know if you want to generate some code to compare tables by referencing pg_tables or svv_columns. In this code I had 2 tables that I'd created by reading svv_columns metadata table, and I wanted to created a case statement for each variable, so I'd have the two variables from each table side by side plus a check variable which I'd use for summarising later:
select ' coalesce(a.'||a.column_name||',''0'') as a_'||a.column_name||', coalesce(b.'||b.column_name||',''0'') as b_'||b.column_name||', case when a_'||a.column_name||'=b_'||b.column_name||' then 0 else 1 end as chk_'||a.column_name||','
from tbl_a_vars a,
tbl_b_vars b
where a.column_name=b.column_name;

Update rows where a combination of multiple attributes is IN the table

I want to update the fields of a table WHERE the combination of three other attributes is IN another table. I am having some difficulties with the syntax, so any help is appreciated.
You would normally use EXISTS for this:
SELECT *
FROM a
WHERE EXISTS (
SELECT 1
FROM b
WHERE a.col1 = b.col1 AND a.col2 = b.col2 AND a.col3 = b.col3
)
Convert the above to an UPDATE query.

Netezza Update a Table Column by Joining to Another Table

I am getting an error by running an update, but I can not figure out where the issue is in Netezza. I appreciate some help.
ERROR [42S02] ERROR: relation does not exist DEVML_WORK.AGRINSHPUN.A
update Table A
set A.COL1 = B.COL2
from A left outer join B
on A.CU_NUM=B.CU_NUM;
In general performance on correlated updates in Netezza is slow. Below are two examples that will get your query to work. The second in my experience speeds up large updates.
-- Slow but works
update Table A
set A.COL1 = B.COL2
from B
where A.CU_NUM=B.CU_NUM;
--Faster
update A set col1 = sub.col2
from (select a.rowid as rown, b.COL2
from A a inner join
B b
on a.cu_num= b.cu_num) sub
where rowid = sub.rown;