views:

46

answers:

2

Looking for the easist/most scalable way to do a set "difference" in SQL Server see below. alt text

If you can't tell from the picture i am looking for everything that is not in the intersection.

I have seen one way to do it:

select * from (      
    (select 'test1' as a, 1 as b)
 union all
  (select 'test2' as a , 2 as b union all select 'test1' as a , 1 as b )
)un group by a,b  having count(1)=1

But i fear what would happen if i used two large sets (i will not be querying from select '' constant statements, my queries will be pulling from real tables.)

EDIT:

Possible solution...

drop table #temp_a;
drop table #temp_b;

 go


  select * into #temp_a from (
   select 1 as num, 'String' as two, 'int'as three, 'purple' as four union all
   select 2 as num, 'dog' as two, 'int'as three, 'purple' as four union all
   select 3 as num, 'dog' as two, 'int'as three, 'cat' as four ) a 

select * into #temp_b from (
  select 1 as num, 'String' as two, 'decimal'as three, 'purple' as four union all
  select 2 as num, 'dog' as two, 'int'as three, 'purple' as four union all
  select 3 as num, 'dog' as two, 'int'as three, 'dog' as four ) b 





   SELECT IsNull(a.num, b.num) A,IsNull(a.two, b.two) B, IsNull(a.three, b.three) C,                  
      IsNull(a.four, b.four) D 
     FROM #temp_a a 
   FULL OUTER JOIN #temp_b b ON (a.num=b.num AND a.two=b.two and a.three=b.three and a.four=b.four)
    WHERE   (a.num is null or b.num is null  )

RESULTS:

1 String int purple

3 dog int cat

1 String dec purple

3 dog int dog

+7  A: 

How about something like this?

SELECT A, B FROM Table1 EXCEPT SELECT A,B FROM Table2
UNION
SELECT A, B FROM Table2 EXCEPT SELECT A,B FROM Table1

Here is an example with the FULL OUTER JOIN method (assuming A is not nullable in both tables)

SELECT IsNull(Table1.A, Table2.A) a,IsNull(Table1.B, Table2.B) B
FROM Table1 
FULL OUTER JOIN Table2 ON (Table1.A=Table2.A AND Table1.B=Table2.B)
WHERE Table1.A is null or Table2.A is null
JohnFx
What does the IsNull part achieve? It it just a means to "show" what is missing?
Nix
For rows that only have a record in one of the tables (the ones you want) there will be a null in one table or the other. For example either Table1.A will be null or Table2.A will be null for each row. The Isnull grabs the value from whichever side has a value.
JohnFx
+4  A: 

What you're after is called a Full Outer Join, which SQL Server supports.

OMG Ponies
I initially thought something like that:select * from (select 'test1' as a, 1 as b) OneFULL JOIN (select 'test2' as a , 2 as b union all select 'test1' as a , 1 as b ) Two ON One.a <> Two.a AND One.b <> Two.bHowever it's not (run both SQL)
Joel Mansford
yes, but you also have to filter out all the matches after the join: `WHERE keyA is NULL OR keyB is NULL`
Remus Rusanu