Joining two tables on column A or column B in SQL - sql

I have two tables called Plan and Actual. Every row in each table represents a unique item, and I need to find items that are in the Plan table, but not the Actual table, and vice versa.
There are three columns that uniquely identify each item, and the value for each of these columns may or may not be null.
For Example:
Say "Plan" looks like this:
ID_1 ID_2 ID_3
aaa Null Null
Null 111 Null
Null Null 123
bbb 222 Null
ccc Null 456
Null 333 789
ddd 444 202
Say "Actual" looks like this:
ID_1 ID_2 ID_3
aaa Null Null
Null 111 Null
bbb 222 Null
Null 333 789
Null 555 Null
eee Null 303
Using SQL, how can I identify the "In plan not in actual" rows of:
Null Null 123
ccc Null 456
ddd 444 202
And in "In actual not in plan" rows of:
Null 555 Null
eee Null 303
Thank you for your help!

If you are using ORACLE, you can use the operator MINUS. It will select rows in table "Plan" not in table "Actual".
SELECT ID_1, ID_2, ID_3
FROM Plan
MINUS
SELECT ID_1, ID_2, ID_3
FROM Actual;
If you are using SQL Server; use EXCEPT instead of minus.

You can use the LEFT JOIN. Below is the example with MySql.
In plan not in actual
SELECT Plan.* FROM Plan
LEFT JOIN Actual ON (Plan.ID_1 = Actual.ID_1 AND Plan.ID_2 = Actual.ID_2 AND Plan.ID_3 = Actual.ID_3)
WHERE Actual.ID_1 IS NULL AND Actual.ID_2 IS NULL AND Actual.ID_3 IS NULL;
In actual not in plan
SELECT Actual.* FROM Actual
LEFT JOIN Plan ON (Plan.ID_1 = Actual.ID_1 AND Plan.ID_2 = Actual.ID_2 AND Plan.ID_3 = Actual.ID_3)
WHERE Plan.ID_1 IS NULL AND Plan.ID_2 IS NULL AND Plan.ID_3 IS NULL;

Related

How to create SQL query with two inner join's and an if case

I try co create a SQL query with two inner joins and an if case. I create an example to explain what I mean:
ID
Typ
Case
123
AAA
zzz
124
BBB
yyy
125
CCC
yyy
Typ1
ID1
AAA
888
BBB
999
CCC
777
ID2
Result
666
1
555
2
777
3
In words, the query should do:
Search in the first table for ID 125, so I get Typ CCC and Case yyy
If case is yyy then search in the second table for CCC in column Typ1, here I get the ID 777 and then search in the third table for 777 in column ID2 to get the result 3.
If case is not yyy then just show me the results of the first table.
The result should be:
ID
Typ
Result
123
AAA
No match
124
BBB
No match
125
CCC
3
I hope you can understand what I try to explain :)
You want to select data from the first table and only show data from the other tables where appropriate. So, outer join the other tables.
select t1.id, t1.typ, t3.result
from t1
left outer join t2 on t2.typ1 = t1.typ and t1.case = 'yyy'
left outer join t3 on t3.id2 = t2.id1
order by t1.id;

identify NULL and update for same key column in oracle

I have a test table having below details:
ID Key_COLUMN final_Value
1 aaa 1234
2 bbb 2345
3 bbb NULL
4 ccc 456
5 ccc 145
Desired Output:
--final_value updated from NULL to 2345 based key_column (bbb)
ID Key_COLUMN final_Value
1 aaa 1234
2 bbb 2345
3 bbb 2345
4 ccc 456
5 ccc 145
Identify KEY column having NULL and value and update NULL with the value.
this update requied on huge amount of data
Please assist.
You can use window functions:
select t.*,
coalesce(final_value, max(final_value) over (partition by key_column)) as imputed_final_value
from t;
If you wanted an update -- to actually change the data -- you can use a correlated subquery:
update t
set final_value = (select t2.final_value
from t t2
where t2.key_column = t.key_column and
t2.final_value is not null and
rownum = 1
)
where final_value is null;

SQL Select Return Rows If Column Contain Value or Null Value Base on Key Columns

It was a bit difficult to describe my requirements based on the title, however I'll post with a table sample and result expectation.
I have a table (lets call it TBL_K) that looks like this:
KEY1 KEY2 VALUE1 VALUE2
abc 123 NULL NULL
abc 123 9999 1111
abc 123 9999 1111
ghd 123 NULL NULL
ghd 123 NULL NULL
tiy 134 4444 NULL
tiy 134 4444 NULL
hhh 981 NULL NULL
I want my Select statement to return the result in:
KEY1 KEY2 VALUE1 VALUE2
abc 123 9999 1111
ghd 123 NULL NULL
tiy 134 4444 NULL
hhh 981 NULL NULL
I have came up with own solution with creating two sub-tables with a left outer join but I want to see if there are other ways of creating this result.
It seems nearly to use max() :
select key1, key2, max(val1), max(val2)
from TBL_K tk
group by key1, key2;
SELECT
A.KEY1,
A.KEY2,
B.VALUE1,
B.VALUE2
FROM
(
SELECT
Z.KEY1,
Z.KEY2,
TRIM(Z.VALUE1) VALUE1,
TRIM(Z.VALUE2) VALUE2
FROM
TBL_K Z
WHERE
TRIM(Z.VALUE1) IS NULL
GROUP BY
Z.KEY1,
Z.KEY2,
Z.VALUE1,Z.VALUE2) A LEFT OUTER JOIN
(
SELECT
Y.KEY1,
Y.KEY2,
TRIM(Y.VALUE1) VALUE1,
TRIM(Y.VALUE2) VALUE2
FROM
TBL_K Y
WHERE
TRIM(Y.VALUE1) IS NOT NULL
GROUP BY
Y.KEY1,
Y.KEY2,
Y.VALUE1,Y.VALUE2) B
ON
(A.KEY1 = B.KEY1
AND A.KEY2 = B.KEY2)

SQL Server two tables with same columns but pick data with no null

I have below sample data, two temp tables with same structure, but I need to get one table output, with taking best values between two tables (best values here is NO NULL's). Ignore null values between two same columns in two tables.
Table 1
Prog OrderNO ORDERKey OrigType REBNO REBACC
A 1 1234 FACILITY NULL NULL
A 2 1234 FACILITY NULL NULL
A 3 1234 FACILITY NULL NULL
Table 2
Prog OrderNO ORDERKey OrigType REBNO REBACC
A 1 NULL NULL 1234 456
A 2 NULL NULL 1234 456
A 3 NULL NULL 1234 456
OUTPUT
Prog OrderNO ORDERKey OrigType REBNO REBACC
A 1 1234 FACILITY 1234 456
A 2 1234 FACILITY 1234 456
A 3 1234 FACILITY 1234 456
Use COALESCE() combined with a FULL OUTER JOIN:
SELECT
COALESCE( Table1.Prog, Table2.Prog ) AS Prog,
COALESCE( Table1.OrderNo, Table2.OrderNo ) AS OrderNo,
COALESCE( Table1.OrderKey, Table2.OrderKey) AS OrderKey,
COALESCE( Table1.OrigType, Table2.OrigType ) AS OrigType,
COALESCE( Table1.RebNo, Table2.RebNo) AS RebNo,
COALESCE( Table1.RebNo, Table2.RebNo) AS RebAcc
FROM
Table1
FULL OUTER JOIN Table2 ON
Table1.Prog = Table2.Prog
AND
Table1.OrderNo = Table2.OrderNo

SQL - Joining a matrix based on criteria

Hoping someone can help me out here as I appear to being going around in circles as SQL isn't my strong point.
I'm at a loss if I can solve the problem with a join but I suspect not.
Problem:
Essentially I have a table and I need to match codes against a lookup table to see which codes are valid and which are not.
Table: tblMatrix
ID family0 family1 family2 family3 family4
1000 AAALL ZZZAA 11111 NULL NULL
1001 AAALL ZZZAA 11122 NULL NULL
1002 AAALL ZZZBB 11111 NULL NULL
1003 AAALL ZZZBB 11122 NULL NULL
1004 AAARR ZZZAA 11111 NULL NULL
1005 AAARR ZZZAA 11122 XXX11 NULL
1006 AAARR ZZZBB 11111 NULL NULL
1007 AAARR ZZZBB 11122 NULL NULL
The comparison is against the following table:
tblComparision
ID code1 code2 code3 code4
4034 AAALL 11122 NULL NULL
5555 AAARR ZZZAA NULL NULL
6667 11122 AAARR
In a stored procedure, I am looping each row in the tblMatrix and essentially need to a count of if any combination of the codes exist in tblComparison.
So for example, ID 1000 is valid as no combation exists. However, ID 1001 is not valid as both AAALL and 11122 have occurred.
Note also that the codes may not be in the correct order so ID 1007 would not be valid as both AAARR and 11122 exist.
Any thoughts as to how I would achieve this. Would several joins work?
The closest I've got to it working is below. Essentially, it starts to fail when the I family1 isn't a match but not sure how to avoid this.
select * from tblMatrix2 as t1
join tblComparison as t2
on
(t1.family0 = t2.code1 or t1.family0 = t2.code2 or t1.family0 = t2.code3 )
join tblComparison as t3
on
(t1.family1 = t3.code1 or t1.family1 = t3.code2 or t1.family1 = t3.code3 )
join tblComparison as t4
on
(t1.family2 = t4.code1 or t1.family2 = t4.code2 or t1.family2 = t4.code3 )
where t1.id = 10001;
Any help would or pointers would be greatly appreciated!
You can list all values by making a union of the fields (no match will not be shown here):
SELECT sub.id,
CASE WHEN MAX (sub.cn) = 1 THEN 'Valid' ELSE 'Invalid' END status
FROM ( SELECT fam.id, COUNT (lst.id) cn
FROM (SELECT id, family0 family FROM tblMatrix
UNION ALL
SELECT id, family1 FROM tblMatrix
UNION ALL
SELECT id, family2 FROM tblMatrix
UNION ALL
SELECT id, family3 FROM tblMatrix
UNION ALL
SELECT id, family4 FROM tblMatrix) fam
INNER JOIN
(SELECT id, code1 code FROM tblComparison
UNION
SELECT id, code2 FROM tblComparison
UNION
SELECT id, code3 FROM tblComparison
UNION
SELECT id, code4 FROM tblComparison) lst
ON fam.family = lst.code
WHERE fam.family IS NOT NULL AND lst.code IS NOT NULL
GROUP BY fam.id, lst.id) sub
GROUP BY sub.id
ORDER BY id
Bonus info:
These union'ed lists transform your tables to something managable in sql with no repeating columns (like code1,code2 etc.). You could simply change the tables accordingly to have a better data model (whithout NULL):
create table tblMatrix (id int, family varchar2(5));
create table tblComparison (id int, code varchar2(5));
If you need to make family or code groups, just add a column for that.