SQL查找非空列

时间:2008-12-01 11:59:39

标签: sql

我有一个时间序列数据表,我需要查找在给定时间段内至少包含一个非空值的所有列。到目前为止,我使用以下查询:

select max(field1),max(field2),max(field3),... 
   from series where t_stamp between x and y

之后,如果结果包含非空值,则检查结果的每个字段。

该表有大约70列,一个时间段可以包含> 100k条目。

我想知道是否有更快的方法来执行此操作(仅使用标准sql)。

编辑: 不幸的是,重构表设计不适合我。

8 个答案:

答案 0 :(得分:5)

EXISTS操作可能会更快,因为它可以在找到符合条件的任何行(相对于您正在使用的MAX)时立即停止搜索。这取决于您的数据以及SQL服务器的智能程度。如果您的大多数列具有高速率的非空数据,则此方法将快速查找行并且应该快速运行。如果您的列大多是NULL值,那么您的方法可能会更快。我会给他们两个镜头,看看它们是如何优化的以及它们如何运行。另请注意,如果数据分布发生显着变化,性能可能会随时间而变化。

另外,我只在MS SQL Server上测试了这个。我一年多没有编写严格的ANSI兼容SQL代码,所以我不确定这是完全通用的。

SELECT
     CASE WHEN EXISTS (SELECT * FROM Series WHERE t_stamp BETWEEN @x AND @y AND field1 IS NOT NULL) THEN 1 ELSE 0 END AS field1,
     CASE WHEN EXISTS (SELECT * FROM Series WHERE t_stamp BETWEEN @x AND @y AND field2 IS NOT NULL) THEN 1 ELSE 0 END AS field2,
...

编辑:只是为了澄清,MAX方法可能更快,因为它可以通过数据单次传递来确定这些值。从理论上讲,这里的方法也可以,并且可能少于完整传递,但是优化器可能无法识别所有子查询都是相关的,因此它可能会为每个子查询执行单独的传递。这仍然可能更快,但正如我所说,这取决于你的数据。

答案 1 :(得分:1)

使用不同的表格设计会更快:

create table series (fieldno integer, t_stamp date);

select distinct fieldno from series where t_stamp between x and y;

拥有一个包含70个“相似”字段的表通常不是一个好主意。

答案 2 :(得分:1)

当你说“更快的方式”时,如果你的意思是更快的方式来运行查询,那么是的,这是如何做到的:每列分成一个查询:

select top 1 field1 from series where t_stamp between x and y and field1 is not null

select top 1 field2 from series where t_stamp between x and y and field2 is not null

select top 1 field3 from series where t_stamp between x and y and field3 is not null

这样,您就不会在整个表中进行表扫描以找到最大值。相反,数据库引擎会在找到非空值后立即停止。假设您的数据不是99%的空值,这可以让您更快地执行 - 但代价是需要更多的编程时间来设置它。

答案 3 :(得分:1)

这个怎么样...您查询可以迭代的字段名称列表。

select 'field1' as fieldname from series 
   where field1 is not null and t_stamp between x and y
UNION
select 'field2' from series where field2 is not null 
... etc

然后你有一个记录集,它只包含非空字段的字符串名称。然后,您可以遍历此记录集以将您的真实查询构建为动态SQL,并忽略没有任何数据的字段。当没有与where子句匹配的crieteria时,“select'field2'”将不返回字符串。

答案 4 :(得分:0)

编辑:我想我误解了这个问题......这会给你带有非空值的所有。我会留在这里,以防它帮助某人,但它不是你的问题的答案。谢谢@Pax

我想你想使用COALESCE

SELECT ... WHERE COALESCE(fild1, field2, field3) IS NOT NULL

答案 5 :(得分:0)

首先,使用标准SQL这是一个非常糟糕的主意,因为并非所有DBMS最后都使用NULL进行排序。

你可以采用各种棘手的方法,而且大多数都会无比缓慢。

我建议你(排序)对数据库进行更多规范化,以便每个列都在一个单独的表中,这样可以使选择更容易,但这可能不是你想要的。

编辑问题后:如果重构表设计不是一个选项,那么您给定的解决方案可能是最好的,特别是如果您在所有70列上都有索引。

虽然这可能会减慢插入速度,但您可能希望使用非索引表来获得最大插入速度,并定期将数据(隔夜?)传输到索引表,该表将以最佳速度运行您的选择(通过避免全表扫描。)

答案 6 :(得分:0)

select count(field1),count(field2),count(field3),... 
   from series where t_stamp between x and y

将告诉您每列中有多少个非空值。不幸的是,它并不比你现在这样做的好多了。

答案 7 :(得分:0)

试试这个:

SELECT CASE WHEN field1 IS NOT NULL THEN '' ELSE 'contains null' END AS field1_stat,
       CASE WHEN field2 IS NOT NULL THEN '' ELSE 'contains null' END AS field2_stat,
... for every field to be checked
FROM   series
WHERE  foo IN bar
GROUP BY CASE WHEN field1 IS NOT NULL THEN '' ELSE 'contains null' END,
         CASE WHEN field2 IS NOT NULL THEN '' ELSE 'contains null' END 
... etc

这将为您提供表格中