tags:

views:

98

answers:

6

I have a list or set of values that I would like to know which ones do not currently exist in a table. I know I can find out which ones do exist with:

SELECT * FROM Table WHERE column1 IN (x,x,x,x,x)

The set is the values I am checking against. Is there a way to find out which values in that set do not exist in column1? Basically, I'm looking for the inverse of the sql statement above.

This is for a report, so all I need is the values that don't exist to be returned back.

I have and could do this with a left join and putting the values in another table, but the values I check are always different and was hoping to find a solution that didn't involve clearing a table and inserting data first. Trying to find a better solution for me if one exists.

+1  A: 
  • Put the values you want to check for in a table A
  • LEFT OUTER JOIN the table A against your Table WHERE Table.column1 IS NULL

    SELECT column1 FROM A LEFT OUTER JOIN Table ON A.column1 = Table.column1 WHERE Table.column1 IS NULL

This will only show the rows that exist in A but not in Table.

Konerak
Yes, I've done this, but it's something I have to do regularly and the data is really temporary - it's not super convenient to put it in another table and run the query against it. Was hoping for a single query solution.
MacAnthony
That's possible to, just use a select statement instead of the table A.
Konerak
@MacAnthony - There's no single query solution. Queries pull data out of tables, so, the data must be in a table in order for the query to return it.
Donnie
Right, but you can use a subquery instead of creating a table, as Mark Byers showed.
Konerak
So how do I use a set (x,x,x,x) as a table then?
MacAnthony
@Mac One possibility might be a split function. To convert a string like 'x,y,z' to a table format. Especially if this is just an ad hoc need that you have. There might be better ones around but here's one I found with a quick Google. http://www.eggheadcafe.com/community/aspnet/13/10021854/fnsplit.aspx
Martin Smith
You can't use a subquery to turn a set into a table unless you want a dynamic number of `UNION`s to a bunch of single line selects.
Donnie
A: 

One way you can do it is: SELECT * FROM Table WHERE column1 NOT IN(...);

Daniel Marques
A: 

Use the NOT operator:

SELECT * FROM Table WHERE column1 NOT IN (x,x,x,x,x)

Cornel Creanga
No, this will select all the rows where the column is NOT in the list. Imagine he has a list 'A B C D E' and he wants to see WHICH of those 5 characters do not appear in the table. Your reply can give him 'F G H', while he maybe wants to see 'C D' if those don't exist.
Konerak
+2  A: 
WITH    q(x) AS
        (
        SELECT  x1
        UNION ALL
        SELECT  x2
        UNION ALL
        SELECT  x3
        )
SELECT  x
FROM    q
WHERE   x NOT IN
        (
        SELECT  column1
        FROM    [table]
        )
Quassnoi
+2  A: 

You can also use EXCEPT as well as the OUTER JOIN e.g.

SELECT * FROM
(
SELECT -1 AS N
UNION 
SELECT 2 AS N
) demo 
EXCEPT 
SELECT     number
FROM         spt_values
Martin Smith
+1, it's elegant
Quassnoi
I had some regex parsing to build the union statement, but this worked well.
MacAnthony
A: 

As you want some of the values from the set in the result, and you can't take them from the table (as you want the ones that doesn't exist there), you have to put the set in some kind of table or result so that you can use that as source.

You can for example make a temporary result, that you can join against the table to filter out the ones that does exist in the table:

select set.x
from (
  select 1 as x union all
  select 2 union all
  select 3 union all
  select 4 union all
  select 5
) as set
left join Table as t on t.column1 = set.x
where t.columnn1 is null
Guffa