2

我有一个包含大量列的查询。我想选择并非所有列都等于 0 的行。

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

这真的是最整洁的方法吗?

假设我需要将其更改为在所有列为 1 或负数时忽略它。它需要大量的剪切和粘贴。

4

6 回答 6

4

看起来这 45 个单独的列具有相似的含义。因此,我鼓励您正确规范化此表。如果你这样做了,查询会更简单,并且可能会执行得更好。

于 2010-03-08T18:08:21.593 回答
2

您可以参数化查询并将其放入存储过程或表值函数中。无论您选择什么值,您只需要编写固定次数的查询(每种操作类型一次)。

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)
于 2010-03-08T17:13:34.107 回答
1

您可以添加一个计算列来为您进行计算。从技术上讲,它并不整洁,只是现在当您在任何查询中使用它时,您只需检查计算列而不是重复计算。

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)
    )
);

如果您的数字以某种方式被限制为 >= 0,您可以做一些稍微整洁的事情,例如:

WHERE col1 + col2 + col3 = 0 -- or 45, if there are 45 such columns
                             -- and you are looking for each column = 1
于 2010-03-08T17:11:28.170 回答
1

(1) 您在条件中使用了错误的连接词 - 您需要 OR 而不是 AND。

修改问题后,上述观察不再正确。

(2) 如果您有 45 列需要过滤,那么您将很难做得比您所写的更好。虽然很痛...

这个观察仍然正确。

于 2010-03-08T17:12:06.577 回答
1

您可以使用校验和。但是,我不知道 CHECKSUM 的内部结构,所以不能保证它适用于大型数据集。

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
于 2010-03-08T17:58:40.893 回答
0

您可以创建规范化结构的视图并将其用作此查询的源:

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

于 2010-03-08T19:41:03.383 回答