Apache IoTDB中ALL量化比较遇Null返回Null,如何获取确定布尔值?
问题:Apache IoTDB 2.0.5中ALL量化比较遇Null返回异常结果
使用Apache IoTDB 2.0.5进行嵌套查询,通过ALL量化比较判断表t1中设备d01的s1值是否大于表t2中设备d01的所有s1值,但子查询包含null值时,结果返回null而非预期的true。
示例原始数据
表t1
| time | device_id | s1 |
|---|---|---|
1970-01-01T08:00:00.001+08:00 | d01 | 30 |
1970-01-01T08:00:00.002+08:00 | d01 | 40 |
1970-01-01T08:00:00.003+08:00 | d01 | 50 |
1970-01-01T08:00:00.004+08:00 | d01 | 60 |
1970-01-01T08:00:00.005+08:00 | d01 | 70 |
表t2
| time | device_id | s1 |
|---|---|---|
1970-01-01T08:00:00.001+08:00 | d01 | 30 |
1970-01-01T08:00:00.002+08:00 | d01 | 40 |
1970-01-01T08:00:00.003+08:00 | d01 | null |
执行的SQL
SELECT s1, s1 > ALL ( SELECT s1 FROM t2 WHERE device_id = 'd01' ) AS greater_than_all FROM t1 WHERE device_id = 'd01';
实际结果
| s1 | greater_than_all |
|---|---|
| 30 | false |
| 40 | false |
| 50 | null |
| 60 | null |
| 70 | null |
预期结果
期望50、60、70大于表t2中设备d01的所有非null的s1值(30、40),因此这些行的greater_than_all应返回true:
| s1 | greater_than_all |
|---|---|
| 30 | false |
| 40 | false |
| 50 | true |
| 60 | true |
| 70 | true |
解决方案
方法一:子查询中过滤Null值
在子查询的WHERE条件中添加s1 IS NOT NULL,直接排除Null值,让ALL比较仅针对非Null的s1值:
SELECT s1, s1 > ALL ( SELECT s1 FROM t2 WHERE device_id = 'd01' AND s1 IS NOT NULL -- 过滤Null值 ) AS greater_than_all FROM t1 WHERE device_id = 'd01';
方法二:使用MAX函数替代ALL量化比较
因为s1 > ALL(子查询)等价于s1 > MAX(子查询结果)(当子查询存在非Null值时),而MAX函数会自动忽略Null值,这样可以更简洁地实现需求:
SELECT s1, s1 > ( SELECT MAX(s1) FROM t2 WHERE device_id = 'd01' ) AS greater_than_all FROM t1 WHERE device_id = 'd01';
原理说明
SQL遵循三值逻辑,任何与null的比较结果都是null。当ALL量化比较的子查询包含null时,只要有一个比较结果为null,整个表达式就会返回null。上述两种方法通过过滤Null或利用聚合函数自动忽略Null的特性,规避了这个问题,从而得到预期的布尔结果。
内容的提问来源于stack exchange,提问作者偶然望月
相关产品推荐
相关产品推荐

