当前位置: 首页 > news >正文

SparkSQL 子查询 IN/NOT IN 对 NULL 值的处理

SparkSQL 子查询 IN/NOT IN 对 NULL 值的处理

官网:https://spark.apache.org/docs/4.0.0/sql-ref-functions.html

https://spark.apache.org/docs/4.0.0/sql-ref-null-semantics.html#innot-in-subquery

在这里插入图片描述

Unlike the EXISTS expression, IN expression can return a TRUE, FALSE or UNKNOWN (NULL) value.
EXISTS 不同,IN 表达式可能返回三种布尔状态:

  • TRUE:当前值在集合中;
  • FALSE:当前值不在集合中;
  • UNKNOWN(即 NULL):当表达式中涉及了 NULL 值时,无法确定真假。

Conceptually a IN expression is semantically equivalent to a set of equality condition separated by a disjunctive operator (OR).For example, c1 IN (1, 2, 3) is semantically equivalent to (c1 = 1 OR c1 = 2 OR c1 = 3).

从语义上讲,IN 表达式等价于多个等于条件用 OR 连接起来。

c1 IN (1, 2, 3)

相当于:

c1 = 1 OR c1 = 2 OR c1 = 3

As far as handling NULL values are concerned, the semantics can be deduced from the NULL value handling in comparison operators(=) and logical operators(OR).

对于 NULL 值的处理方式,可以基于比较运算符(如 =)和逻辑运算符(如 OR)的行为来推导。 也就是说,IN 的行为是建立在底层 SQL 对 NULL 处理规则之上的。


To summarize, below are the rules for computing the result of an IN expression.

  • TRUE is returned when the non-NULL value in question is found in the list
  • FALSE is returned when the non-NULL value is not found in the list and the list does not contain NULL values
  • UNKNOWN is returned when the value is NULL, or the non-NULL value is not found in the list and the list contains at least one NULL value

IN 表达式的计算规则如下:

情况结果
当前值不为 NULL,并且存在于列表中TRUE
当前值不为 NULL,但不在列表中,且列表中没有 NULL值FALSE
当前值为 NULL,或者列表中有 NULL值但当前值不在其中UNKNOWN

只要列表中包含 NULL,即使当前值不在列表中,也不能简单地返回 FALSE,而是返回 UNKNOWN


IN Demo:


1:子查询结果只有 NULL

%sql
WITH person AS (SELECT * FROM VALUES('a', 25),('b', 30),('c', 35),('d', 40),('e', 50),('d', 50)AS person(name, age)
)
SELECT * FROM person
WHERE age IN (SELECT null);

空表✅

在这里插入图片描述

  • IN (NULL) 返回的是 UNKNOWN,不会匹配任何行。

2:子查询包含 NULL 和有效值

%sql
WITH person AS (SELECT * FROM VALUES('a', 25),('b', 30),('c', 35),('d', 40),('e', 50),('f', 50)AS person(name, age)
)
SELECT * FROM person
WHERE age IN (SELECT age FROM VALUES(50), (NULL)AS sub(age)
);
-- 虽然子查询里有 NULL,但只要匹配到具体值就会返回;

只有 age = 50 的记录被选中。

在这里插入图片描述


3:子查询包含 NULL 和多个值

%sql
WITH person AS (SELECT * FROM VALUES('a', 25),('b', 30),('c', 35),('d', 40),('e', 50),('f', 50)AS person(name, age)
)
SELECT * FROM person
WHERE age IN (SELECT age FROM VALUES(25), (30), (NULL)AS sub(age)
);
-- 虽然子查询里有 NULL,但只要匹配到具体值就会返回;

在这里插入图片描述


4: 主表中存在 NULL 值,同时子查询结果也包含 NULL

在这里插入图片描述

条件是否被选中原因
age = 25✅ 是匹配列表中的值
age = NULL❌ 否NULL IN (…) → UNKNOWN
age = 35/40/50❌ 否不匹配列表中的非 NULL 值,且列表中有 NULL → UNKNOWN

NOT IN Demo:

只要 NOT IN 后面的子查询包含 NULL,整个条件就会变成 UNKNOWN没有任何行被返回

避免这个问题,需要在子查询中加上 WHERE age IS NOT NULL

1:子查询结果只有 NULL

  • NOT IN (只要有null)不返回任何结果
%sql
WITH person AS (SELECT * FROM VALUES('a', 25),('b', 30),('c', 35),('d', 40),('e', 50),('d', 50)AS person(name, age)
)
SELECT * FROM person
WHERE age NOT IN (SELECT null);

在这里插入图片描述

子查询中包含 NULLNOT IN 整体返回 UNKNOWN,SQL 不会将其视为 TRUE,所以没有行满足条件。


2: 子查询包含 NULL 和有效值

  • NOT IN (只要有null)不返回任何结果
%sql
WITH person AS (SELECT * FROM VALUES('a', 25),('b', 30),('c', 35),('d', 40),('e', 50),('f', 50)AS person(name, age)
)
SELECT * FROM person
WHERE age NOT IN (SELECT age FROM VALUES(50), (NULL)AS sub(age)
);

在这里插入图片描述


3: 主表中存在 NULL 值,同时子查询结果也包含 NULL

  • NOT IN (只要有null)不返回任何结果
%sql
WITH person AS (SELECT * FROM VALUES('a', 25),('b', 30),('c', null),('d', 40),('e', 50),('f', 50)AS person(name, age)
)
SELECT * FROM person
WHERE age NOT IN (SELECT age FROM VALUES(50), (NULL)AS sub(age)
);

在这里插入图片描述


Spark官方对于各种函数处理null值的说明:

https://spark.apache.org/docs/4.0.0/sql-ref-null-semantics.html

在这里插入图片描述

http://www.dtcms.com/a/295304.html

相关文章:

  • 【分布式锁】什么是分布式锁?分布式锁的作用?
  • Windows计算器项目全流程案例:从需求到架构到实现
  • 宝塔通过docker部署JupyterHub指南【常见错误处理】
  • 深入解析文件操作(下)- 文件的(顺序/随机)读写,文件缓冲区,更新文件
  • 【AI】Jupyterlab中数据集的位置和程序和Pycharm中的区别
  • 20-ospf技术
  • MIT线性代数01_方程组的几何解释
  • 绿色转向的时代红利:创新新材如何以技术与标准主导全球铝业低碳重构
  • 旅行短视频模糊的常见原因及应对方法
  • 内网穿透:打破网络限制的利器,内外网概念、穿透原理、实际操作方法步骤
  • 【LeetCode 热题 100】39. 组合总和——(解法一)选或不选
  • 【物联网】基于树莓派的物联网开发【16】——树莓派GPIO控制LED灯实验
  • 暑期算法训练.7
  • 97.2%灵敏度,桐树基因MSI NGS 2249 Panel——低肿瘤含量MSI检测的王者
  • CIRL:因果启发的表征学习框架——从域泛化到奖励分解的因果革命
  • LLM:Day1
  • 【Linux】linux基础开发工具(一) 软件包管理器yum、编辑器vim使用与相关命令
  • Web前端:JavaScript some()迭代方法
  • 前端如何利用多通道发布(MCP)打造高效AI驱动应用?
  • Hadoop磁盘I/O瓶颈的监控与优化:从iostat指标到JBOD vs RAID的深度解析
  • 2025真实面试试题分析-iOS客户端开发
  • Spring工程中集成多个redis数据源
  • iOS WebView 加载失败与缓存刷新问题排查实战指南
  • [iOS开发工具] 【iOS14以及以下】cydia商店按键精灵iOS新版V2.X安装教程
  • STM32 IAP升级失败之谜:时钟源配置的陷阱与解决方案
  • 【AJAX】XMLHttpRequest、Promise 与 axios的关系
  • JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
  • 【计算机网络】第六章:应用层
  • socket请求
  • 第二十章 W55MH32 WOL示例