pd.read_sql中IS NOT NULL语句失效,如何正确排除NULL值?
解决pd.read_sql中
IS NOT NULL无法排除NULL行的问题 问题背景
使用pandas的pd.read_sql执行SELECT语句时,试图用WHERE field_name IS NOT NULL排除指定字段为NULL的行,但结果仍包含该字段为NULL的记录。目前临时用length(field_name) > 0实现过滤,需要找到更准确的解决方案。
可能原因
出现这种情况通常不是pd.read_sql的问题,而是数据库中该字段的“空值”并非标准SQL NULL:
- 字段存储的是空字符串(
'')或全空白字符(如空格、制表符),这类值会被IS NOT NULL判定为非NULL,但length(...) > 0能过滤掉空字符串(全空白字符的length仍大于0,无法被过滤) - 字段中存储的是字符串
'NULL'而非真正的SQL NULL值,此时IS NOT NULL自然不会生效
可行解决方案
1. SQL层面同时过滤标准NULL和空白/空字符串
直接在WHERE条件中同时处理两种情况,确保覆盖所有无效空值:
import pandas as pd Result3 = pd.read_sql(""" SELECT gcdu_flatten.cbid_code, gcdu_flatten.incorporation_country, gcdu_flatten.gid_original, gcdu_flatten.local_cust_id, gcdu_flatten.saracen_id FROM rm_views_uat_wave.gcdu_flatten WHERE gcdu_flatten.etlmonth = '2024-04-30' AND gcdu_flatten.saracen_id IS NOT NULL AND TRIM(gcdu_flatten.saracen_id) != '' """, conn)
TRIM()函数会去除字符串首尾的空白字符,确保全空格的记录也能被过滤。
2. 先排查字段实际存储的值
先查询该字段的所有不同值,明确所谓的“NULL”到底是什么类型:
check_df = pd.read_sql(""" SELECT DISTINCT saracen_id, CASE WHEN saracen_id IS NULL THEN 'TRUE_NULL' ELSE 'NOT_NULL' END AS null_status, LENGTH(saracen_id) AS string_length FROM rm_views_uat_wave.gcdu_flatten WHERE gcdu_flatten.etlmonth = '2024-04-30' """, conn) print(check_df)
通过输出结果可以清楚看到:哪些是真正的SQL NULL,哪些是空字符串、空白字符或'NULL'字符串,再针对性调整过滤条件。
3. 读取后用pandas二次过滤
如果SQL层面调整不便,也可以在读取数据后用pandas进行过滤:
Result3 = pd.read_sql(""" SELECT gcdu_flatten.cbid_code, gcdu_flatten.incorporation_country, gcdu_flatten.gid_original, gcdu_flatten.local_cust_id, gcdu_flatten.saracen_id FROM rm_views_uat_wave.gcdu_flatten WHERE gcdu_flatten.etlmonth = '2024-04-30' """, conn) # 过滤标准NULL、空字符串、全空白字符 Result3 = Result3[ Result3['saracen_id'].notna() & (Result3['saracen_id'].str.strip() != '') ]
内容的提问来源于stack exchange,提问作者SCH_245
相关产品推荐
相关产品推荐

