PySpark中IN子查询报错修复:IN/EXISTS子查询仅可用于Filter/Join
修复PySpark中CASE WHEN里IN子查询的报错问题
这个错误是因为PySpark SQL不支持在CASE WHEN的条件判断里直接使用IN子查询,这类子查询只能用在WHERE(Filter)或者JOIN关联逻辑中。下面给两种可行的修复方案:
方案一:将子查询结果转为静态列表(适合小数据集)
先查询出campanhas表中所有的PGTO值,收集成一个本地列表,再直接把这个列表写到CASE WHEN的IN条件里:
- 先获取PGTO的去重列表:
# 收集campanhas表中所有PGTO的去重值 pgto_values = spark.sql("SELECT DISTINCT PGTO FROM campanhas").rdd.map(lambda row: row[0]).collect() # 转成SQL兼容的字符串格式(比如'val1','val2') pgto_str = "','".join(pgto_values)
- 把生成的字符串拼到你的SQL语句中:
CASE WHEN MEIO IN ('CARTÃO A','CARTÃO ML','Cartão C') AND PGTO IN ('{}') THEN 'GH' -- 可根据需求添加ELSE分支 ELSE 'OTHER' END
注意:这种方法只适合campanhas表数据量不大的情况,因为collect()会把数据拉到Driver节点,数据量太大可能导致内存问题。
方案二:用JOIN关联表来判断存在性(适合大数据集)
通过左连接或者左半连接,把campanhas表的PGTO关联到主表,生成一个标志位来判断PGTO是否存在,再在CASE WHEN里用这个标志位:
WITH main_with_flag AS ( SELECT t.*, -- 关联成功说明PGTO在campanhas里存在 CASE WHEN c.PGTO IS NOT NULL THEN 1 ELSE 0 END AS pgto_exists FROM your_main_table t LEFT JOIN campanhas c ON t.PGTO = c.PGTO ) SELECT *, CASE WHEN MEIO IN ('CARTÃO A','CARTÃO ML','Cartão C') AND pgto_exists = 1 THEN 'GH' ELSE 'OTHER' END AS your_target_column FROM main_with_flag
如果只需要保留PGTO存在的记录,可以用LEFT SEMI JOIN替换LEFT JOIN,这样不需要生成标志位,直接在WHERE里过滤;但如果要保留所有主表记录,还是用左连接加标志位更合适。
内容的提问来源于stack exchange,提问作者Vivian
相关产品推荐
相关产品推荐

