Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL查找非空列_Sql - Fatal编程技术网

SQL查找非空列

SQL查找非空列,sql,Sql,我有一个时间序列数据表,我需要找到在给定时间段内至少包含一个非空值的所有列。到目前为止,我正在使用以下查询: select max(field1),max(field2),max(field3),... from series where t_stamp between x and y 之后,我检查结果的每个字段是否包含非空值 该表大约有70列,一个时间段可以包含>100k个条目 我想知道是否有更快的方法(仅使用标准sql)来实现这一点 编辑: 不幸的是,重构表格设计不是我的选择。编辑

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

select max(field1),max(field2),max(field3),... 
   from series where t_stamp between x and y
之后,我检查结果的每个字段是否包含非空值

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

我想知道是否有更快的方法(仅使用标准sql)来实现这一点

编辑:
不幸的是,重构表格设计不是我的选择。

编辑:我想我误解了这个问题。。。这将为您提供所有具有非空值的行。我会把它留在这里,以防它对某人有所帮助,但这不是你问题的答案。谢谢@Pax

我想你应该使用:


选择。。。如果COALESCE(fild1、field2、field3)不为NULL

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

create table series (fieldno integer, t_stamp date);

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

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

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

有各种各样的棘手的方法可以做到这一点,大多数都是无休止的缓慢

我建议您(某种程度上)进一步规范化数据库,使每个列都位于一个单独的表中,这将使选择更容易,但这可能不是您想要的

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

尽管这可能会大大降低插入速度,但您可能希望使用非索引表以获得最大的插入速度,并定期(隔夜?)将数据传输到索引表,以便以最佳速度运行SELECT(通过避免全表扫描)

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

试试这个:

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
这将为您提供表中“null”字段组合的摘要,当您说“执行此操作的更快方法”时,如果您指的是运行查询的更快方法,那么是的,下面介绍如何执行:将其拆分为每列一个查询:

从x和y之间的t_戳记和字段1不为空的序列中选择前1个字段1

从x和y之间的t_戳记和字段2不为空的序列中选择前1个字段2

从x和y之间的t_戳记和字段3不为空的序列中选择前1个字段3


这样,您就不会在整个表中进行表扫描以找到最大值。相反,数据库引擎将在找到非空值时立即停止。假设您的数据不是99%的空值,这将使您的执行速度更快,但这将以牺牲更多的编程时间为代价。

这如何。。。您可以查询可以迭代的字段名列表

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子句匹配的条件时,“select'field2'”将不会返回字符串。

EXISTS操作可能会更快,因为它可以在找到与条件匹配的任何行时停止搜索(相对于您使用的最大值)。这取决于您的数据和SQL server的智能程度。如果您的大多数列具有高比率的非空数据,那么此方法将快速查找行,并且应该快速运行。如果您的列大部分为空值,那么您的方法可能会更快。我会给他们两人一个机会,看看他们各自是如何优化的,以及他们是如何运行的。还要记住,如果数据分布发生显著变化,性能可能会随着时间的推移而变化

另外,我只在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方法可能更快,因为它可以通过一次数据传递来确定这些值。理论上,这里的方法也可以,并且可能不到一个完整的过程,但是您的优化器可能无法识别所有子查询都是相关的,因此它可能会对每个子查询执行单独的过程。这可能会更快,但正如我所说的,这取决于您的数据。

他正在寻找至少有一个NULL的列,如果它们都为NULL,您的解决方案会为该行提供NULL。我认为这对检测单个列没有帮助。@Pax:请重新阅读问题陈述。他想找到非空的列,所以筛选行至少会有一个开始。您是正确的,如果大多数列不为null,那么EXISTS将完全超过MAX。但是,在某些时段,70个列中只有30个被填充,对于EXISTS,执行速度将慢10到15倍。我猜优化器没有我希望的那么聪明:(
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,
...