我有一个包含很多列的表(比如200),它们都是布尔值。我想知道其中哪一个至少有一个记录设置为true。我提出了以下查询,该工作正常:
SELECT sum(Case When [column1] = 1 Then 1 Else 0 End) as column1,
sum(Case When [column2] = 1 Then 1 Else 0 End) as column2, sum(Case
When [column3] = 1 Then 1 Else 0 End) as column3, FROM [tablename];
它将返回“真实”的行数。对于一个专栏。但是,这比我需要的信息更多,因此可能需要更昂贵的查询。该查询将继续扫描所有记录的所有字段,即使这不是必需的。
答案 0 :(得分:0)
如果你在一个表上使用boolean实际上有200列/字段,那么类似下面的内容应该可以工作。
SELECT CASE WHEN column1 + column2 + column3 + ... + column200 >= 1 THEN 'Something was true for this record' ELSE NULL END AS My_Big_Field_Test
FROM [TableName];
答案 1 :(得分:0)
如果您只想知道最后一个布尔字段的行,则需要测试每个行。
像这样(也许):
SELECT ROW.*
FROM TABLE ROW
WHERE ROW.COLUMN_1 = 1
OR ROW.COLUMN_2 = 1
OR ROW.COLUMN_3 = 1
OR ...
OR ROW.COLUMN_N = 1;
答案 2 :(得分:0)
我刚刚学到了一些可能有用的CHECKSUM(*)。请尝试以下代码:
DECLARE @T TABLE (
b1 bit
,b2 bit
,b3 bit
);
DECLARE @T2 TABLE (
b1 bit
,b2 bit
,b3 bit
,b4 bit
,b5 bit
);
INSERT INTO @T VALUES (0,0,0),(1,1,1);
INSERT INTO @T2 VALUES (0,0,0,0,0),(1,1,1,1,1);
SELECT CHECKSUM(*) FROM @T;
SELECT CHECKSUM(*) FROM @T2;
您将从结果中看到,无论一行中有多少列,如果它们都是值为0的位列,则CHECKSUM(*)的结果始终为0.
这意味着您可以在查询中使用WHERE CHECKSUM(*)<>0
来节省引擎排除所有值均为0的行的麻烦。可能会提高性能。
即使它没有,但要知道这是一件很好的事情。
编辑:
您可以对每列执行EXISTS()函数。我知道EXISTS()函数在找到存在的值时会停止扫描。如果行数多于列数,则可能性能更高。如果列数多于行数,那么在每列上使用SUM()的当前查询可能是您可以做的最快的事情。
答案 3 :(得分:0)
我不在我的机器前面,但您也可以尝试按位或操作符:
SELECT * FROM [table name] WHERE column1 | column2 | column3 = 1
亚瑟的OR回答是我提供的另一个建议。尝试一些不同的建议,看看查询计划。另请参阅磁盘读取和CPU使用情况。 (SET STATISTICS IO ON和SET STATISTICS TIME ON)。
参见任何方法给出欲望结果和最佳表现......然后告诉我们: - )
答案 4 :(得分:0)
您可以使用表格
的查询SELECT
CASE WHEN EXISTS (SELECT * FROM [Table] WHERE [Column1] = 1) THEN 0 ELSE 1 END AS 'Column1',
CASE WHEN EXISTS (SELECT * FROM [Table] WHERE [Column2] = 1) THEN 0 ELSE 1 END AS 'Column2',
...
这种效率关键取决于你的桌子有多稀疏。如果列中的每一行都有0
值,那么搜索1
值的任何查询都需要进行全表扫描,除非有索引。这个场景(数百万行和数百列)的一个非常好的选择是columnstore index。从SQL Server 2012开始支持这些;从SQL Server 2014开始,它们不会导致表只读(这是它们采用的主要障碍)。
使用列存储索引,每个子查询应该需要恒定的时间,因此查询作为一个整体(事实上,对于数百列,此查询变得如此之大,以至于您可能会遇到输入缓冲区和需要将其拆分为较小的查询)。如果没有索引,只要表不稀疏,此查询仍然有效 - 如果它“快速”运行到具有1
值的行,它就会停止。