9

Lets consider I have a table 'Tab' which has a column 'Col'

The table 'Tab' has this data -

Col
1
2
3
4
5

If I have a set of values (2,3,6,7). I can query the values that are present in the table and the list by suing the query

Select Col from Tab where col IN (2,3,6,7)

But, if I want to return the values in the list that are not present in the table i.e. only (6,7) in this case. What query should I use?

3
  • What RDBMS and version are you on? Commented Jul 8, 2010 at 13:03
  • In comments you've appended to various answers, I see that you're dealing with string values, not integers, and that your input list contains somewhere in the neighborhood of 70 values. Are you looking to write a stored procedure? Using dynamically-generated SQL? Parameterized query? As Martin asked, what DB platform & version are you working with? That will tell us what feature set we have to work with. (XML, UDF, etc.) Is Linq->SQL an option? Commented Jul 8, 2010 at 13:44
  • @Martin I am working on SQL Server 2005. @Toby I am just trying to use a sql query to retrieve the rows that satisfy the conditions I mentioned in the question. Commented Jul 8, 2010 at 17:19

7 Answers 7

3

The problem I believe is that your trying to find values from you in statement. What you need to do is turn your in statement into a table and then you can determine which values are different.

create table #temp
(
value int
)

insert into #temp values 1
insert into #temp values 2
insert into #temp values 3
insert into #temp values 4

select
 id
from
 #temp
where
 not exists (select 1 from Tab where Col = id)

A better alternative would be to create a table-valued function to turn your comma-delimited string into a table. I don't have any code handy, but it should be easy to find on Google. In that case you would only need to use the syntax below.

select
 id
from
 dbo.SplitStringToTable('2,3,6,7')
where
 not exists (select 1 from Tab where Col = id)

Hope this helps

Sign up to request clarification or add additional context in comments.

3 Comments

I used an example here for simplicity. I actually am dealing with around 70 values. Writing 70 insert statements isn't really practical. I wonder if there is a simpler way to do this. Thanks for the answer anyway.
How are you determining the values?
am sorry I added the comment before trying the latter part of your answer i.e. to create a table-valued function to turn comma separated string into a table. I tried this out now it gets simple once I get the list of values into a table. Thank you.
3

A SQL Server 2008 method

SELECT N FROM (VALUES(2),(3),(6),(7)) AS D (N)
EXCEPT
Select Col from Tab

Or SQL Server 2005

DECLARE @Values XML

SET @Values = 
'<r>
    <v>2</v>
    <v>3</v>
    <v>6</v>
    <v>7</v>
</r>' 


SELECT 
    vals.item.value('.[1]', 'INT') AS Val
FROM @Values.nodes('/r/v') vals(item)
EXCEPT
Select Col from Tab

Comments

2

one way would be to use a temp table:

DECLARE @t1 TABLE (i INT) 
INSERT @t1 VALUES(2) 
INSERT @t1 VALUES(3)
INSERT @t1 VALUES(6) 
INSERT @t1 VALUES(7)

SELECT i FROM @t1 WHERE i NOT IN (Select Col from Tab)

1 Comment

I used an example here for simplicity. I actually am dealing with around 70 values. Writing 70 insert statements isn't really practical. I wonder if there is a simpler way to do this. Thanks for the answer anyway.
0

One method is

declare @table table(col int)
insert into @table
select 1 union all
select 2  union all
select 3  union all
select 4  union all
select 5 


declare @t table(col int)
insert into @t
select 2 union all
select 3 union all
select 6 union all
select 7 

select t1.col from @t as t1 left join @table as t2 on t1.col=t2.col
where t2.col is null

Comments

0

Do you have a [numbers] table in your database? (See Why should I consider using an auxiliary numbers table?)

SELECT
    [Tab].*
FROM
    [numbers]
    LEFT JOIN [Tab]
        ON [numbers].[num] = [Tab].[Col]
WHERE
    [numbers].[num] IN (2, 3, 6, 7)
    AND [Tab].[Col] IS NULL

1 Comment

Thanks for the answer. I wasn't aware of this. But, I used an example here for simplicity. I actually am dealing with varchar and not numbers.
0

I think there are many ways to achive this, here is one.

SELECT a.col 
FROM 
  (SELECT 2 AS col UNION ALL SELECT 3 UNION ALL SELECT 6 UNION ALL SELECT 7) AS a
WHERE a.col NOT IN (SELECT col FROM Tab)

Comments

0

Late to the party...

SELECT 
    '2s' = SUM(CASE WHEN Tab.Col = 2 THEN 1 ELSE 0 END),
    '3s' = SUM(CASE WHEN Tab.Col = 3 THEN 1 ELSE 0 END),
    '6s' = SUM(CASE WHEN Tab.Col = 6 THEN 1 ELSE 0 END),
    '7s' = SUM(CASE WHEN Tab.Col = 7 THEN 1 ELSE 0 END)
FROM
(SELECT 1 AS Col, 'Nums' = 1 UNION SELECT 2 AS Col,'Nums' = 1 UNION SELECT 3 AS Col,      'Nums' = 1 UNION SELECT 4 AS Col, 'Nums' = 1 UNION SELECT 5 AS Col, 'Nums' = 1 ) AS Tab
GROUP BY Tab.Nums

BTW, mine also gives counts of each, useful if you need it. Like if you were checking a product list against what you have in inventory. Though you can write a pivot for that better, just don't know how off the top of my head.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.