6

I wish to join two (or more) tables based on a set of columns that are present in all tables that take part in the join. In other words I wish to join tables based on the intersection set of columns. However each table has extra columns which are unique to that table.

Intersection set

Example

#: A number
-: NULL

Table A

+------+------+------+
| Col1 | Col2 | ColA |
+------+------+------+
| A    | A    | #    |
| A    | B    | #    |
+------+------+------+

Table B

+------+------+------+
| Col1 | Col2 | ColB |
+------+------+------+
| A    | A    | #    |
| B    | B    | #    |
+------+------+------+

Result

+------+------+------+------+
| Col1 | Col2 | ColA | ColB |
+------+------+------+------+
| A    | A    | #    | #    |
| A    | B    | #    | -    |
| B    | B    | -    | #    |
+------+------+------+------+

I've come up with a solution but the performance is horrid, performance is an issue. I don't want to pollute you with that solution. I'd much rather have a fresh set of eyes on this :)

Looking forward to seeing your solutions. Thank you for your time. It's much appreciated.

UPDATE

Thank you for all the responds. However it seems I didn't explain the problem well enough. (Haven't tested all answers yet)

But note how Table B has a row that's not present in Table A.

Table B
+------+------+------+
| Col1 | Col2 | ColB |
+------+------+------+
| B    | B    | #    |
+------+------+------+

And Table A vice versa.

The solution I've come up with unions all tables together on the intersection set of columns to generate a skeleton.

Skeleton:    
SELECT Col1, Col2 FROM TableA
UNION
SELECT Col1, Col2 FROM TableB

Once I have the skeleton I LEFT OUTER JOIN for each table.

LEFT OUTER JOIN TableA AS a ON a.Col1=skeleton.Col1 AND a.Col2=skeleton.Col2
LEFT OUTER JOIN TableB AS b ON b.Col1=skeleton.Col1 AND b.Col2=skeleton.Col2

So the final query looks like this

SELECT s.*, a.ColA, b.ColB 
FROM 
(
    SELECT Col1, Col2
    FROM TableA
    UNION
    SELECT Col1, Col2
    FROM TableB
) s
LEFT OUTER JOIN TableA a ON a.Col1=s.Col1 AND a.Col2=s.Col2
LEFT OUTER JOIN TableB b ON b.Col1=s.Col1 AND b.Col2=s.Col2
Snæbjørn
  • 10,322
  • 14
  • 65
  • 124

4 Answers4

3

Just the thing for a full outer join:

select  coalesce(a.Col1, b.Col1) as Col1
.       coalesce(a.Col2, b.Col2) as Col2
,       a.ColA
,       b.ColB
from    A a
full outer join
        B b
on      a.Col1 = b.Col1
        and a.COl2 = b.Col2
Andomar
  • 232,371
  • 49
  • 380
  • 404
0

This might help:

SELECT Col1, Col2, ColA
FROM A
GROUP BY Col1, Col2, ColA
UNION ALL
SELECT Col1, Col2, ColB
FROM B
GROUP BY ColB 

Or take a look here:

Combine two tables for one output

Community
  • 1
  • 1
Valentin Vrinceanu
  • 679
  • 1
  • 12
  • 24
0

You can resolve a double outer join with a Union:

SELECT
  TableA.Col1,TableA.Col2,
  TableA.ColA,TableB.ColB
FROM TableA
LEFT JOIN TableB ON TableA.Col1=TableB.Col1 AND TableA.Col2=TableB.Col2

UNION

SELECT
  TableB.Col1,TableB.Col2,
  TableA.ColA,TableB.ColB
FROM TableB
LEFT JOIN TableA ON TableA.Col1=TableB.Col1 AND TableA.Col2=TableB.Col2
Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
0

Oh my. Be wishful what you care for.

-- Sample data.
declare  @TableA as Table ( Col1 VarChar(8), Col2 VarChar(8), ColA Int NULL )
insert into @TableA ( Col1, Col2, ColA ) values
  ( 'A', 'A', 42 ), ( 'A', 'B', 7 )
declare  @TableB as Table ( Col1 VarChar(8), Col2 VarChar(8), ColB Int NULL )
insert into @TableB ( Col1, Col2, ColB ) values
  ( 'A', 'A', 999 ), ( 'B', 'B', -1 )
select * from @TableA
select * from @TableB

-- The query.  Use the aggregate(s) of your choice: SUM, MIN, MAX, AVG.
select Col1, Col2, Sum( ColA ), Sum( ColB )
  from (
  select A.Col1, A.Col2, A.ColA, Cast( NULL as Int ) as [ColB]
    from @TableA as A
  union all
  select B.Col1, B.Col2, Cast( NULL as Int ), B.ColB
    from @TableB as B ) as Edgar
  group by Col1, Col2
HABO
  • 15,314
  • 5
  • 39
  • 57