I want to join few tables:
table1:
A B_key B_version C D
123 abc 1 ccc 11
123 abc 2 ddd 11
456 dfg 1 rrr 22
789 vvv 1 55
table2:
A E F
123 s 5
456 r
111 t 2
table3:
B_key B_version G
abc 1 aa
abc 1 bb
abc 2 aa
abc 2 cc
dfg 1 aa
so the result would look like this:
A B_key B_version C D E F G
123 abc 1 ccc 11 s 5 aa
123 abc 1 ccc 11 s 5 bb
123 abc 2 ddd 11 s 5 aa
123 abc 2 ddd 11 s 5 cc
456 dfg 1 rrr 22 r aa
789 vvv 1 55
Version can go as high as 8.
IF I don't have A, B_key or B_version - the line is useless. Otherwise I need to keep all the information I do have.
In reality I have many more columns.
I've tried:
SELECT table1.A, table 1.B_key, table 1.B_version, table 1.C, table 1.D,
table2.E, table2.F,
table3.G
FROM table1
LEFT JOIN table2
ON table1.A = table2.A
LEFT JOIN table3
ON table1.B_key = table3.B_key AND
table1.B_version = table3.B_version
and the same with FULL JOIN.
It ends up the same: for every B_key only the highest B_version is kept, while the others disappear.
How can I avoid loosing information?
You can use left joins among tables as below :
select t1.A, t1.B_key, t1.B_version, t1.C, t1.D, t2.E, t2.F, t3.G
from table1 t1
left join table2 t2 on t2.A = t1.A
left join table3 t3 on t3.B_key = t1.B_key and t3.B_version = t1.B_version
Demo
in order to bring also the rows for unmatched values for join conditions.
If I understand correctly, you want all the b_keys and b_versions from table1 and table3. Then you want to bring in the other data. That suggests left joins
select . . .
from ((select B_key, B_version
from table1
) union -- on purpose to remove duplicates
( select B_key, B_version
from table3
)
) bb left join
table1 t1
on t1.b_key = bb.b_key and
t1.b_version = bb.b_version left join
table2 t2
on t2.a = t1.a left join
table3 t3
on t1.b_key = bb.b_key and
t1.b_version = bb.b_version;
Related
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
I Have 3 tables as below. In table1, if value in column id is present then join that column with other tables, if null I want to join with ref column from table 1 with other tables. What is the best way to do this
table1
Name id ref
abc 123
abc 456
edc 345 432
asd 678
table 2
city id ref
NY 123
WA 875
CA 345 432
SA 678
table 3
city orders
NY 78954
WA 123546
CA 789
SA 1
I want below result: ABC has 123 in id hence NY. ASD has 678, so considered ref column in table1 to join with other 2 tables
Name city order
ABC NY 78954
EDC CA 789
ASD SA 1
You can use left joins for this purpose:
select t1.*, t3.city, t3.count
from table1 t1 left join
table2 t2
on t1.id = t2.id left join
table2 t2r
on t1.ref = t2.ref and t1.id is null left join
table3 t3
on t3.city = coalesce(t1.city, t2.city);
Note: This returns all rows from table1, even those with no match in either column. If this is an issue, add:
where t2.id is not null or t2.ref is not null
I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D
I have an inner join on 2 tables.
Consider
Table1
sid name
1 abc
2 xyz
Table2
sdid sid detailname
1 1 a
2 1 b
3 2 x
So my query looks like below
SELECT *
FROM table1 t1
INNER JOIN table2 t2
ON t1.sid=t2.sid
the result i get is
sid name sdid sid detailname
1 abc 1 1 a
1 abc 2 1 b
2 xyz 3 2 x
I want to modify this query to get the highest 'sdid' from table 2
my end result should look like
sid name sdid sid detailname
1 abc 2 1 b
2 xyz 3 2 x
Include one more subquery in the join to get the max sdid for each sid from table2.
SELECT t1.sid,t1.name,t2.sdid,t2.sid,t2.detailname
FROM table1 t1
INNER JOIN table2 t2 ON t1.sid=t2.sid
INNER JOIN (select max(sdid) as maxsdid, sid from table2 group by sid) t21
ON t21.sid=t2.sid and t21.sdid = t2.sdid
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.