Seeking a Teradata Merge alternative - sql

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)

Related

SQL to Match columns from 2 different tables using a Select statement

I have 2 tables A & B with columns 6 columns in each table.
Table A has lesser rows than table B.
I want to write a Select Statement where if the below condition satisfies
-----A.Col1=B.Col1 and A.Col2=B.Col2 and A.Col3=B.Col3 and A.Col4=B.Col4 and A.Col5=B.Col5 and A.Col6=B.Col6-----
if all conditions are satisfied then in a new column say "Match" else "NoMatch"
How do I do that ?
I would suggest using exists. If you want a new column in A:
select a.*,
(case when exists (select 1
from b
where A.Col1 = B.Col1 and A.Col2 = B.Col2 and
A.Col3 = B.Col3 and A.Col4 = B.Col4 and
A.Col5 = B.Col5 and A.Col6 = B.Col6
)
then 'match' else 'nomatch'
end) as flag
from a;
Note: If you want the new column on B, the logic is the same but the two tables are reversed.
If any of the columns can have NULL values, then you need to take that into account.
You can use CASE statement and I am considering that you need all data from tableB and matching data from tableA as follows:
select b.*, a.*,
case when A.Col1=B.Col1 and A.Col2=B.Col2
and A.Col3=B.Col3 and A.Col4=B.Col4
and A.Col5=B.Col5 and A.Col6=B.Col6
then 'Match'
else 'No match'
end as res
from tableB b
left join TableA a
on A.Col1=B.Col1 and A.Col2=B.Col2
and A.Col3=B.Col3 and A.Col4=B.Col4
and A.Col5=B.Col5 and A.Col6=B.Col6

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.

SQL Error: ORA-00905: missing keyword, can someone please tel me whats wrong with the below merge statement

MERGE INTO table_a PARTITION (x) A
USING (SELECT distinct col1,col2 FROM table_b)b
ON (A.col1=B.col1(+) AND A.col2=B.col2(+))
WHEN MATCHED THEN
UPDATE SET col3='Y'
WHEN NOT MATCHED THEN
UPDATE SET col3='N';
The WHEN NOT MATCHED clause cannot perform an UPDATE - what rows is it supposed to update if it didn't find any?
If you want to update A depending on whether there's an existing row in B, one approach is to pull A into the merge query (this assumes your table A has a primary key PK):
MERGE INTO table_a PARTITION (x) tgt
USING (
SELECT A.PK, B.col1, B.col2
FROM table_a A
LEFT JOIN table_b b ON A.col1 = B.col1 AND A.col2 = B.col2) src
ON (src.pk = tgt.pk)
WHEN MATCHED THEN
UPDATE SET col3 = (CASE WHEN src.col1 IS NOT NULL THEN 'Y' ELSE 'N' END);

join clause, match or null

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.

How to choose a proper filter for an sql join

If I have table A and table B, each with one column:
A:
col1
1
2
3
1
B:
col1
1
1
4
and I want all rows from A and the matching rows from B, only when the column has non null value in both tables, which one should I use?
select * from A left join B on A.col1 = B.col1 and A.col1 is not null AND B.col1 is not null;
select * from A left join B on A.col1 = B.col1 where A.col1 is not null OR B.col1 is not null;
select * from A left join B on A.col1 = B.col1 and (A.col1 is not null OR B.col1 is not null;)
My guess is that the first and the third are the same and will provide the desired output.
If you want to skip null values and you want to link both tables only on existing values you should use an INNER JOIN, the null check is redundant:
SELECT A.*
FROM A INNER JOIN B ON A.col1 = B.col1
NULL will never match any other value (not even NULL itself), unless the join condition explicitly uses the IS NULL or IS NOT NULL predicates.
In a comment you said you are checking for more than nulls in this case I would probaly take thederived table or CTE approach. Dervied table shown below as you did not specify which database backend, so I don't know if you can use CTEs.
select
from
(select from tablea where test is not null or test <>'' or test<>'N/A') a
JOin
(select from tableb where test is not null or test <>'' or test<>'N/A')b
ON a.col1 = b.col1
You just need
select * from A left join B on A.col1 = B.col1
NULL will never match anything (when not compared with IS NULLand the like), therefore NULL in A won't match anything in B.
Since you want all the rows from A, below query should work:
select * from A left outer join B on A.col1 = B.col1 where A.col1 is not null and A.col1<>'N/A' and A.col1<>''
http://sqlfiddle.com/#!2/98501/14