tags:

views:

43

answers:

2

I have a "server" table which has a column named 'SN' in mysql, when do query to retrive servers with some sns from 'sn1' to 'sn10000', we can:

select * from server where sn in ('sn1','sn2','sn3',...'sn10000');

If there is only one sn in 'sn1'-'sn10000' which not exists in database, then the query above will retrive 9999 rows of result.

The question is how can I easily get which one in 'sn1'-'sn10000' is not exists in database except the additional work, such as handling the result with shell script etc.

I have an ugly sql like below can use:

select * from (select 'sn1' as sn 
        union select 'sn2' 
        union select 'sn3'
        ....
        union select 'sn10000') as SN 
where not exists (select id from server where server.sn=SN.sn);

Is Anyone has other better methods? Thanks.

+1  A: 

Stick your sn1, sn2, sn3... sn10000 values in a temporary table, and then use Joins.

Select server.* from server inner join tempt on (tempt.value = server.sn)

will give you the ones that match, where as

Select sn.* from server right outer join tempt on (tempt.value = server.sn) 
where server.somefield is Null

should take care of finding the missing ones.

Martin Milan
Thanks for your answer. It looks like there is no way to achieve this without temporary table. The method proposed in my question is indeed using the temporary table too.Thanks a lot.
leivli
Note the lack of unions...
Martin Milan
+1  A: 

Your query is perfectly fine for the intended use, but on MySQL the NOT IN and LEFT JOIN/IS NULL are more effecient that NOT EXISTS. Here are your alternatives:

NOT IN

SELECT * 
  FROM (          SELECT 'sn1' as sn 
        UNION ALL SELECT 'sn2' 
        UNION ALL SELECT 'sn3'
        ....
        UNION ALL SELECT 'sn10000') as SN 
 WHERE sn.sn NOT IN (SELECT s.id FROM SERVER s)

LEFT JOIN/IS NULL

   SELECT s.id
     FROM SERVER s
LEFT JOIN (          SELECT 'sn1' as sn 
           UNION ALL SELECT 'sn2' 
           UNION ALL SELECT 'sn3'
           ....
           UNION ALL SELECT 'sn10000') as SN ON SN.sn = s.id
    WHERE sn.sn IS NULL

You might notice I used UNION ALL, rather than UNION - UNION removes duplicates (which won't happen in your example), making it slower so UNION ALL is a better choice.

OMG Ponies
Thanks for your advice, I wonder there is no any simple method without using temporary table...
leivli