我需要在pyspark中加入2个表,并且这个连接不是来自右表的精确值,而是取最近的值(因为没有完全匹配。
它在常规SQL中工作正常,但在SparkSQL中不起作用。 我正在使用Spark 2.2.1
在常规SQL中:
SELECT a.*,
(SELECT b.field2 FROM tableB b
WHERE b.field1 = a.field1
ORDER BY ABS(b.field2 - a.field2) LIMIT 1) as field2
FROM tableA a
ORDER BY a.field1
工作正常
SparkSQL中的:
...
tableA_DF.registerTempTable("tableA")
tableB_DF.registerTempTable("tableB")
query = "SELECT a.*, \
(SELECT b.field2 FROM tableB b \
WHERE b.field1 = a.field1 \
ORDER BY ABS(b.field2 - a.field2) LIMIT 1) field2 \
FROM tableA a \
ORDER BY a.field1"
result_DF = spark.sql(query)
我遇到以下异常:
pyspark.sql.utils.AnalysisException:在WHERE / HAVING子句之外不支持引用外部查询的u'Expressions
如果Spark 2.2.1不支持它会解决什么问题呢?
提前谢谢你, 加里
答案 0 :(得分:1)
您最好的选择是重构查询,以便从联接表而不是与标量相关的子查询输出field2值。例如:
...
tableA_DF.registerTempTable("tableA")
tableB_DF.registerTempTable("tableB")
query = "SELECT a.*, \
FIRST(b.field2) OVER (ORDER BY ABS(b.field2 - a.field2)) field2 \
FROM tableA a \
JOIN tableB b
ON a.field1 = b.field1 \
ORDER BY a.field1"
result_DF = spark.sql(query)
以这种方式编写时,Catalyst能够解析查询计划。请注意,以上内容已在Spark 2.3.1上进行了测试-此功能可能需要一些最近引入的加窗功能。
对于可能不愿重新定义JOIN或WHERE子句的任何人,Spark 2.4可能包括一些用于关联子查询处理的新功能: https://issues.apache.org/jira/browse/SPARK-18455
更新:不幸的是,SPARK-18455中提到的相关子查询在18年9月11日滑至目标版本3.0.0。在这一点上,我们几乎不可能看到包含该功能的2.x版本,并且从历史上看,为基本主要版本指定的Spark次要功能已经偏离了发展路线。目前,我认为相关子查询主要不在Spark团队的路线图上。