Outer join and unique records in each table - sql

TableA
------
IntId EvId Name Phone1
===== ==== ==== ======
100 aaa xxx 11111
101 bbb yyy 22222
102 ccc zzz 33333
103 bbb asd 44444
104 bbb sdf 55555
TableB
------
IntId ASId Grp Phone2
===== ==== ==== ======
201 bbb yyy 6666
202 ccc zzz 7777
203 bbb asd 8888
204 bbb kkf 9999
205 ddd esd 0000
206 eee ffr 1001
I want to join TableA with TableB using TableA.EvId = TableB.ASId to output {IndId, EvId, Name, Phone1, Grp, Phone2} (using outerjoin as I want all records in TableA with matching TableB columns)
I could do it using below query, but it is giving me duplicates since EvId and ASId have duplicates.
SELECT a.IntId, a.EvId, a.Name, a.Phone1, b.Grp, b.Phone2
FROM TableA a
LEFT OUTER JOIN TableB b
ON a.EvId = b.ASId
If EvId are duplicates, consider that record which has max IntId. Same rule for TableB
My final output should be like this - all unique EvId's in TableA using outerjoin on B
IntId EvId Name Phone1 Phone2 Grp
100 aaa xxx 11111 null null
104 bbb sdf 55555 9999 kkf
102 ccc zzz 33333 7777 zzz
Can you please help me with the query?

You can use ROW_NUMBER():
SELECT a.IntId, a.EvId, a.Name, a.Phone1, b.Grp, b.Phone2
FROM TableA a LEFT OUTER JOIN
(SELECT b.*,
ROW_NUMBER() OVER (PARTITION BY ASId ORDER BY IntID DESC) as seqnum
FROM TableB b
) b
ON a.EvId = b.ASId AND b.seqnum = 1;

Related

How to make LEFT JOIN to rows having max date in BQ?

I have 2 tables in Big Query:
TABLE A
ID
Name
Date_A
field_x
field_y
field_z
xxx
tata
10/11/2021
a
0
1
xxx
tata
11/11/2021
a
1
1
zzz
tutu
01/11/2021
b
0
1
zzz
tutu
05/11/2021
b
1
1
yyy
titi
02/11/2021
c
0
1
uuu
tata
08/11/2021
d
0
0
TABLE B
ID
Name
Date_B
field_A
field_B
xxx
tata
13/11/2021
AA
BB
zzz
tutu
01/11/2021
CC
DD
yyy
titi
11/11/2021
AA
BB
uuu
tata
05/11/2021
DD
DD
And I would like to link (left join on ID and Name) rows from table B to the max date of table A, to get :
ID
Name
Date_A
field_x
field_y
field_z
field_A
field_B
xxx
tata
10/11/2021
a
0
1
NULL
NULL
xxx
tata
11/11/2021
a
1
1
AA
BB
zzz
tutu
01/11/2021
b
0
1
NULL
NULL
zzz
tutu
05/11/2021
b
1
1
CC
DD
yyy
titi
02/11/2021
c
0
1
AA
BB
uuu
tata
08/11/2021
d
0
0
DD
DD
How can I do that in SQL (Big Query) please ? Thanks
Consider below approach
select a.*,
(if(row_number() over win = 1, b, null)).* except(id, name, date_b)
from table_a a
left join table_b b
using(id, name)
window win as (partition by a.id, a.name order by date_a desc)
if applied to sample data in your question - output is
I didn't tested it but I think you should left join the b table to a table in which the max date is indicated. Usage of condition pure on the left table is somewhat unusual though from the definition of left join I expect it to work.
select a_ranked.ID, a_ranked.Name, a_ranked.Date_A
, a_ranked.field_x, a_ranked.field_y, a_ranked.field_z
, b.field_A, b.field_B
from (
select a.*, rank() over (partition by ID, Name order by Date_A desc) as r
from a
) a_ranked
left join b on a_ranked.ID = b.ID and a_ranked.Name = b.Name and a_ranked.r = 1

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;

Hive table join with update

I am a bit stuck , Can any one help me here. I have two tables with the below structure.
Table 1
Id String
Code1 String
Code2 String
Table 2
Id String
UserCode String
UniversalCode String
What i need to do is to replace all value in code1 and code2 with UniversalCode from the table 2. To be more clear , if code1 matches UserCode then repalce Code1 with universalCode and again for the same record if code2 matches with usercode then replace it with UniversalCode. If there is no match retain the value for code1 and code2. I need to have all records from table 1. Table 1 and Table 2 are connected via Id.
I tried the below for one column but got stuck adding code2
SELECT
Id,
CASE WHEN a.Code1 = b.UserCode then b.UniversalCode else a.Code1 end
from table1 a
LEFT OUTER JOIN table2 b ON (a.Id = b.Id and a.code1 = b.UserCode);
Any suggestions to get this done ? , The real scenario has 5-6 columns where i need to apply the same logic.
Test Data
Table 1
1,123,ABCD
1,ABCD,123
1,456,BCD
1,BCD,789
1,789,100
Table 2
1,123,XXX
1,456,YYY
1,789,ZZZ
2,123,XXX
2,456,YYY
2,789,ZZZ
Output
1,XXX,ABCD
1,ABCD,XXX
1,YYY,BCD
1,BCD,ZZZ
1,ZZZ,100
output with a.id=b.id in Join(Please refer below comments for this output)
1 123 XXX 100 100
1 123 123 100 100
1 123 123 100 100
1 ABCD ABCD 101 101
1 ABCD ABCD 101 101
1 ABCD ABCD 101 101
1 456 456 DEF DEF
1 456 YYY DEF DEF
1 456 456 DEF DEF
1 BCD BCD 789 789
1 BCD BCD 789 789
1 BCD BCD 789 ZZZ
1 789 789 CDE CDE
1 789 789 CDE CDE
1 789 ZZZ CDE CDE
1 100 100 HBT HBT
1 100 100 HBT HBT
1 100 100 HBT HBT
1 100 100 123 XXX
1 100 100 123 123
1 100 100 123 123
I'm not sure if I understand you but something like this should help you.
SELECT
a.Id
, CASE WHEN a.Code1 = b.UserCode THEN b.UniversalCode ELSE a.Code1 END AS Code1
, CASE WHEN a.Code2 = b.UserCode THEN b.UniversalCode ELSE a.Code2 END AS Code2
FROM table1 a
LEFT OUTER JOIN
table2 b
ON a.Id = b.Id;
We can try the below query:-
SELECT
Id,
CASE WHEN Code1 = UserCode then UniversalCode else Code1 end,
CASE WHEN Code2= UserCode then UniversalCode else Code2 end
from
(select a.id,a.Code1,a.Code2,b.UserCode,b.UniversalCode
from table1 a
LEFT OUTER JOIN table2 b ON (a.Id = b.Id and a.code1 = b.UserCode) union
select a.id,a.Code1,a.Code2,b.UserCode,b.UniversalCode
from table1 a
LEFT OUTER JOIN table2 b ON (a.Id = b.Id and a.code1 = b.UniversalCode)) dat ;

Oracle 11g - Creating a side by side comparison of table comlumn data

I have a query where I need to extract data in a regular table and put two rows of data into a single row.
I have rows that consist of
StudentID AUDIT_ACTN Audit_Date .....
aaa A 01/01/2010
aaa A 03/04/2011
aaa A 02/02/2013
aaa D 09/10/2010
aaa D 05/06/2011
aaa D 06/07/2013
aaa A 11/12/2014~
bbb A 01/01/2010
bbb A 03/04/2011
bbb A 02/02/2013
bbb D 09/10/2010
bbb D 05/06/2011
bbb D 06/07/2013
bbb A 11/12/2014~
I want output like this
StudentID AUDIT_ACTN Audit_Date StudentID AUDIT_ACTN Audit_Date
aaa A 01/01/2010 aaa D 09/10/2010
aaa A 03/04/2011 aaa D 05/06/2011
aaa A 02/02/2013 aaa D 06/07/2013
aaa A 11/12/2014 NULL NULL NULL
bbb A 01/01/2010 bbb D 09/10/2010
bbb A 03/04/2011 bbb D 05/06/2011
bbb A 02/02/2013 bbb D 06/07/2013
bbb A 11/12/2014 NULL NULL NULL
The A & D data rows are related, a= add the something to the record and d = delete something from the record (something is an indicator). These is logical in that you must add something before you delete it and you cannot add it twice, without deleting it first.
My current script is probably going down the wrong track but here goes;
select a.StudentId,a.Audit_Date,a.AUDIT_ACTN,d.StudentId,Audit_Date,d.AUDIT_ACTN,
from table a
join
(select *
from
(Select StudentId, Audit_Date,AUDIT_ACTN
from table b
Where b.AUDIT_ACTN='D'
order by Audit_Date
)
where rownum=1
) d on a.StudentId = d.StudentId
and a.AUDIT_ACTN='A'
and Select * from (Select Audit_Date
Order by a.StudentId, a.Audit_Date
I know this is wrong but where do I go from here. If anyone can help and point me in the right direction. It would be appreciated.
My current attempts bring me zero rows, when I take out the rownum it brings me a x join returning 12 rows in this case.
thanks
Roger
I think you need aggregate function like below
select
A.StudentId,A.Audit_Date,A.AUDIT_ACTN,
D.StudentId,D.Audit_Date,D.AUDIT_ACTN
from
(Select StudentId, Audit_Date,AUDIT_ACTN,ROW_NUMBER()
OVER (PARTITION BY StudentId order by audit_date) rn
from table b
Where b.AUDIT_ACTN='D'
) D
FULL OUTER JOIN
(Select StudentId, Audit_Date,AUDIT_ACTN,ROW_NUMBER()
OVER (PARTITION BY StudentId order by audit_date) rn
from table b
Where b.AUDIT_ACTN='A'
) A
on A.rn = D.rn and A.StudentId = B.StudentId
I hope this will work

how to get Unique data from one table and the other

If I want to display Order_Number data1 data2 data3 (most current by date changed OtherData1, OtherData2, OtherData3) date_changed the problem is I wasn't just one line, I was getting multiple lines for each order number.
What I would love to get is
1, a, f,q, cc,ccc,abc, 12/2/2014, bob
3, c, b,h, aa,aaa,abc, 12/2/2014, bob
Thanks!
I was working with
SELECT
t.Order_Number,
cr.data1, cr.data2, cr.data3,
t.OtherData1, t.OtherData2, t.OtherData3,
x.date_changed, cr.name
FROM
(SELECT
Order_Number,
Max(date_changed) as date_changed
FROM
table2
GROUP BY
Order_Number) x
JOIN
table2 t ON x.date_changed = t.date_changed
LEFT JOIN
table1 cr ON x.Order_Number = cr.Order_Number
WHERE cr.name = 'bob'
Here are example tables.
Table1:
Order_Number data1 data2 data3 name
1 a f q bob
2 b g g john
3 c b h bob
4 d s j john
Table2:
Order_Number date_changed OtherData1 OtherData2 OtherData3
1 11/30/2014 aa aaa abc
1 12/1/2014 bb bbb def
1 12/2/2014 cc ccc abc
3 12/1/2014 dd aaa def
2 11/30/2014 dd bbb abc
2 12/1/2014 ss ccc def
3 12/2/2014 aa aaa abc
4 11/26/2014 fc wer wsd
Your Join to config_log (Table2) needs to include the entire composite key if you want to retrieve unique rows.
JOIN
conf_log t ON x.date_changed = t.date_changed
And x.Order_Number = t.Order_number
I think you need to have 2 sub querys:
SELECT
Data.Order_Number,
Data.data1, Data.data2, Data.data3,
Data.OtherData1, Data.OtherData2, Data.OtherData3,
Data.date_changed, Data.name
FROM
(SELECT
Order_Number,
Max(date_changed) as date_changed
FROM
table2
GROUP BY
Order_Number) x
JOIN (SELECT
t.Order_Number,
cr.data1, cr.data2, cr.data3,
t.OtherData1, t.OtherData2, t.OtherData3,
t.date_changed, cr.name
FROM table2 t
JOIN table1 cr
ON t.Order_Number = cr.Order_Number) AS Data
ON x.date_changed = data.date_changed
AND x.Order_Number = data.Order_number
WHERE cr.name = 'bob'
The fact that you had cr.name in the where clause means the LEFT JOIN had the same affect as just JOIN.