I have two views which use radically different means to accomplish what I hope is the same end view. One uses complex query expressions and walks entire giant tables and is highly expensive, and the other uses a new boolean bit flag which has been added to the database for precisely the purpose of accelerating this view.

I can write this kind of union, and then (in my program code) use this to determine that a row in view A is not in the results of view B, but I'm hoping I can do this entirely in SQL:

Here's the union I came up with:

select trantype,product_code, 0 as type from vwVIEW1 where key = 'DEMO' 
select trantype,product_code, 1 as type  from vwVIEW2 where key = 'DEMO'
order by product_code, trantype

My old view is fictionally called vwVIEW1 above, and it walks giant database tables to determine its output, whereas vwVIEW2 does a very quick index-lookup on two fields to achieve the same results (select a,b,c from tblUnderlyingTable where tblUnderlyingTable.HeyRickyCanIBeInYourShow=1).

Typical results coming from the above union would in the healthy case, return a pair of rows for each trantype+product_code, plus my invented "type" flag:

trantype product_code  type
-------- ------------  ----
0        MATCHY        0
0        MATCHY        1
0        NONMATCHY     0

Out of the above set of data, I would want to only see the row NONMATCHY, because it is in vwVIEW1 but not in vwVIEW2. All fields in the union above are non-null. No nulls are ever expected in trantype, or product_code.

  • What is the nullability of trantype and product_code? Jan 15, 2013 at 16:38
  • All fields are non-null.
    – Warren P
    Jan 15, 2013 at 16:38

2 Answers 2


You can use a FULL OUTER JOIN for this

     AS (SELECT trantype,
         FROM   vwVIEW1
         WHERE  KEY = 'DEMO'),
     AS (SELECT trantype,
         FROM   vwVIEW2
         WHERE  KEY = 'DEMO')
         ON T1.trantype = T2.trantype
            AND T1.product_code = T2.product_code
WHERE  T1.trantype IS NULL
        OR T2.trantype IS NULL 
  • Oh... That covers either one being null, so either the left-hand-side (T1) or right-hand--side (T1) is null, but the other side is not null, and thus, we have a row returned. Both cases (t1 row missing, t2 row missing) are covered?
    – Warren P
    Jan 15, 2013 at 16:45
  • 1
    @WarrenP - Yes both cases are covered. If the T2 row is missing the corresponding columns will be NULL and if the T1 row is missing the T1 columns will be NULL. You could do something a bit more elaborate with just one set of columns. SELECT ISNULL(T1.trantype, T2.trantype) AS trantype, ISNULL(T1.product_code, T2.product_code) AS product_code, CASE WHEN T1.trantype IS NULL THEN 0 ELSE 1 END AS flag Jan 15, 2013 at 16:49

Here is another approach which presents the data more inline with your sample result:

  SELECT trantype, product_code, [type] = 0 
  FROM dbo.vwVIEW1 WHERE [key] = 'DEMO'
b AS 
  SELECT trantype, product_code, [type] = 1 
  FROM dbo.vwVIEW2 WHERE [key] = 'DEMO'
SELECT trantype, product_code, [type] FROM a 
  EXCEPT SELECT trantype, product_code, [type] = 0 FROM b
SELECT trantype, product_code, [type] FROM b
  EXCEPT SELECT trantype, product_code, [type] = 1 FROM a;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.