4

I am seeing a strange behavior when I do except and union statements in SQL.

I have two tables

Select * from #old

Data looks like this

oid1    oid2    co
   1      11     1
   2      22     1
   3      33     1
   4      55     1

Select * from #new

nid1    nid2    co
   1      11     3
   2      22     1
   3      33     1
   4      44     1
   4      55     1

This is my final query

Select * from #old
    except
    Select * from #new
    union all
    Select * from #new
    except
    Select * from #old

and gives these records

oid1    oid2    co
   1      11     3
   4      44     1

Question I have is.. Shouldn't there be another row in this from the first except clause:

Select * from #old
except
Select * from #new

which is

oid1    oid2    co    
   1      11     1

Shouldn't the final query have 3 rows instead of only 2, since not all columns are the same.

Degan
  • 989
  • 2
  • 16
  • 30
Sarah
  • 1,199
  • 2
  • 21
  • 42

1 Answers1

8

You seem to think that the query is interpreted as:

(Select * from #old
 except
 Select * from #new
)
union all
(Select * from #new
 except
 Select * from #old
)

But no. It is interpreted as:

((Select * from #old
  except
  Select * from #new
 )
 union all
 Select * from #new
)
except
Select * from #old

This is equivalent to:

Select * from #new
except
Select * from #old

which is what your query returns.

This is explained in the documentation:

If EXCEPT or INTERSECT is used together with other operators in an expression, it is evaluated in the context of the following precedence:

  1. Expressions in parentheses

  2. The INTERSECT operator

  3. EXCEPT and UNION evaluated from left to right based on their position in the expression

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
  • 2
    Perfect, thank you so very much. Yes, that's exactly I was interpreting it, learned something new today. Didn't know about those operators rules. Thank you!! – Sarah Aug 02 '18 at 06:30