'SQL Left join avoid duplicates
Let's say this is my Table A:
Col1 Col2 Col3 Col4 Col5
a b c d e
a b c x f
b i j l m
b i j v t
And my second table B:
Col1 Col2 Col3 Col6
a b c g
a b c s
b i j u
b i j h
Table A and B have common colums ( here Col 1, Col 2, and Col 3) and table B has only unique rows, no duplicates. What I want to have is:
Col1 Col2 Col3 Col4 Col5 Col6
a b c d e g
a b c x f null
b i j l m u
b i j v t null
So the thing to do a is a left join on only first match and all others rows from table B that match should be null/empty. I have tried this query :
SELECT A.*, B.Col6,
FROM A
LEFT JOIN
B
ON
A.Col1 = B.Col1
AND A.Col2 = B.Col2
AND A.Col3 = B.Col3
But this gives me duplicates. I also tried with distinct, row_number()b ut still not the expected results. I cannot used subqueries and TOP 1 and limit 1 also does not give the expected result. I have the feeling that it is quite simple but yet still no solution.
Can someone help me?
Solution 1:[1]
You can do a lateral join, as in:
select
x.col1, x.col2, x.col3, x.col4, x.col5,
case when x.rn = 1 then y.col6 end as col6
from (select *, row_number()
over(partition by col1, col2, col3 order by col4) as rn from a) x
left join lateral (
select * from b where (b.col1, b.col2, b.col3) = (x.col1, x.col2, x.col3)
order by col6 limit 1
) y on true
Result:
col1 col2 col3 col4 col5 col6
----- ----- ----- ----- ----- ----
a b c d e g
a b c x f null
b i j l m u
b i j v t null
See running example at DB Fiddle.
Solution 2:[2]
Maybe OUTER APPLY can help you:
SELECT A.*, B.Col6
FROM A
LEFT OUTER APPLY (SELECT TOP 1 *
FROM B WHERE A.Col1 = B.Col1
AND A.Col2 = B.Col2
AND A.Col3 = B.Col3) B
It will returns you exactly one matching from left side, if not you will have NULL as you already shown in your example.
This will work on SQL Server.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | The Impaler |
| Solution 2 |
