tags:

views:

64

answers:

3

Just as I can check if a column does not equal one of the strings given in a set.

SELECT * FROM table1 WHERE column1 NOT IN ('string1','string2','string3');

Is there a single function that I can make sure that multiple columns does not equal a single string? Maybe like this.

SELECT * FROM table1 WHERE EACH(column1,column2,column3) <> 'string1';

Such that it gives the same effect as:

SELECT * FROM table1 WHERE column1 <> 'string1' 
                       AND column2 <> 'string1' 
                       AND column3 <> 'string1';

If not, what's the most concise way to do so?

+4  A: 

I believe you can just reverse the columns and constants in your first example:

SELECT * FROM table1 WHERE 'string1' NOT IN (column1, column2, column3);

This assumes you are using SQL Server.

UPDATE:

A few people have pointed out potential null comparison problems (even though your desired query would have the same potential problem). This could be worked around by using COALESCE in the following way:

SELECT * FROM table1 WHERE 'string1' NOT IN (
     COALESCE(column1,'NA'), 
     COALESCE(column2,'NA'), 
     COALESCE(column3,'NA')
);

You should replace 'NA' with a value that will not match whatever 'string1' is. If you do not allow nulls for columns 1,2 and 3 this is not even an issue.

Abe Miessler
If the columns are nullable this won't return the right results.
Martin Smith
Are you sure. Wouldn't this return the same as his last example? I see your point about null comparisons, but his last example would have the same issue wouldn't it?
Abe Miessler
At least some databases (the one I'm working on this moment, in fact) treat unquoted text in an IN list as string literals (as if they were quoted) and not as identifiers.
Larry Lustig
@Abe - True that's an issue with the original code.
Martin Smith
@Larry, this response `assumes you are using SQL Server` and it seems to work alright in there. What are you using?
Abe Miessler
I'm using R:Base (not that I expect the OP is).
Larry Lustig
try this (in SQL Server), which uses this solution, yet does not return the proper results (because of NULLs): `declare @X table (id int, column1 varchar(3), column2 varchar(3), column3 varchar(3));INSERT @X VALUES (1,null,null,null);INSERT @X VALUES (2,null,'ABC','ABC');INSERT @X VALUES (3,'ABC','X','ABC');INSERT @X VALUES (4,'ABC','X',null);INSERT @X VALUES (4,'ABC','ABC','ABC');SELECT * FROM @X WHERE 'x' NOT IN (column1, column2, column3);` any row that has at least 1 null in column1 or column2 or column3 will not be returned even if the target string is not in any of the columns.
KM
@KM, what is the proper result? if you run the following sql (which is the same as what he said he wanted to reproduce) it returns the same as mine: `SELECT * FROM @X WHERE column1 <> 'x' AND column2 <> 'x' AND column3 <>'x'`
Abe Miessler
To handle NULLS in SQL Server could do `SELECT * FROM @X WHERE 'X' NOT IN (SELECT C FROM (SELECT column1 AS C UNION ALL SELECT column2 UNION ALL SELECT column3) D WHERE C IS NOT NULL)` (Not suggesting **should** though!)
Martin Smith
Abe Miessler, the OP's code you refer to is flawed as well, as it misses rows that have any NULL values. I would think a solution to `Is there a single SQL (or its variations) function to check not equals for multiple columns at once` would be general enough to handle NULLs
KM
@Martin Smith, this would be better to use a "magic number" approach: `select * from @X WHERE 'x' NOT IN (ISNULL(column1,''), ISNULL(column2,''), ISNULL(column3,''));` but nothing is going to use an index unless there is a redesign.
KM
@KM, I see your point but you are still assuming that columns 1,2 and 3 are nullable which is not mentioned anywhere in the OP. I have added a workaround that will allow for nulls. @Martin, what do you think about my updated work around?
Abe Miessler
@KM, updated version of the query for your testing pleasure: `SELECT * FROM @X WHERE 'x' NOT IN (coalesce(column1,'NA'), coalesce(column2,'NA'), coalesce(column3,'NA'));`
Abe Miessler
+3  A: 

No, there is no standard SQL way to do this. Barring any special constraints on what the string fields contain there's no more concise way to do it than you've already hit upon (col1 <> 'String1' AND col2 <> 'String2').

Additionally, this kind of requirement is often an indication that you have a flaw in your database design and that you're storing the same information in several different columns. If that is true in your case then consider refactoring if possible into a separate table where each column becomes its own row.

Larry Lustig
+1, I agree 100% `Additionally, this kind of requirement is often an indication that you have a flaw in your database design`
KM
+1. I'm glad you pointed out that he may not have a normalized database.
JoshD
+1  A: 

The most concise way to do this is

SELECT * FROM table1 WHERE column1 <> 'string1' 
                       AND column2 <> 'string1' 
                       AND column3 <> 'string1';

Yes, I cut & pasted that from your original question. :-)

I'm more concerned why you're wanting to compare against all three columns. It sounds like you might have a table that needs normalization. What are the actual columns of column1, column2 and column3. Are they something like phone1, phone2, and phone3? Perhaps those three columns should actually be in a subtable.

Andy Lester
Lately we've figured that our database had a lot of junk records, in which there are a lot of columns that are just empty strings. I'm looking for those records to delete. I have no control over the database design. Thanks for your response.
Russell