Question

I have a query with loads of columns. I want to select rows where not all the columns are equal to 0.

select * from table
where 
not
( column1 = 0 and
  column2 = 0 and
  column3 = 0 and
  ...
  column45 = 0)

Is this really the tidiest way to do it?

Supposing I then need to change it to ignore when all columns are 1, or negative.. Its a lot of cut and paste..

Was it helpful?

Solution

You could parameterize the query and put it in a stored procedure or table-valued function. You'd only need to write the query a fixed number of times (once per operation type) regardless of the value(s) you choose.

create function dbo.fn_notequal_columns
(
    @value int
)
returns table
as
(
    select * from [table]
    where column1 <> @value and column2 <> @value ...
)

select * from dbo.fn_notequal_columns(0)

OTHER TIPS

It appears as though the 45 individual columns have a similar meaning. As such, I would encourage you to properly normalize this table. If you did, the query would be simpler and would likely perform better.

You could use CHECKSUM. However, I don't know the internals of CHECKSUM so can't guarantee it would work over large datasets.

CREATE TABLE dbo.FooBar (
    keyCol int NOT NULL IDENTITY (1, 1),
    col1 int NOT NULL,
    col2 int NOT NULL,
    col3 int NOT NULL
    )

INSERT FooBar (col1, col2, col3)
SELECT -45, 0, 45
UNION ALL
SELECT 0, 23, 0
UNION ALL
SELECT 0, 0, 0
UNION ALL
SELECT 1, 0, 0

SELECT
   CHECKSUM(col1, col2, col3)
FROM
   dbo.FooBar

SELECT
   *
FROM
   dbo.FooBar
WHERE
   CHECKSUM(col1, col2, col3) = 0

(1) You have the wrong connective in the condition - you need OR and not AND.

With the question amended, the observation above is no longer correct.

(2) If you have 45 columns that you need to filter on, you are going to be hard pressed to do any better than what you have written. Pain though it be...

This observation remains true.

You could add a computed column that does the calculation for you. It is not technically any tidier, except that now when you use it in any query you only have to check the computed column as opposed to repeating the calculation.

CREATE TABLE dbo.foo
(
    col1 INT,
    col2 INT,
    col3 INT,
    all_0 AS
    (
        CONVERT(BIT, CASE 
            WHEN col1 = 0 AND col2 = 0 AND col3 = 0 
            THEN 1 ELSE 0 
        END)
    )
);

You could also do something slightly tidier such as:

WHERE col1 + col2 + col3 = 0 -- or 45, if there are 45 such columns
                             -- and you are looking for each column = 1

you could create a view of a normalized structure and use that as your source for this query:

SELECT all other fields, 'Column1', COL1 FROM tableName
UNION
SELECT all other fields, 'Column2, COL2 FROM TableName
UNION ...
SELECT all other fields, 'Column45', COL45 FROM tableName

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top