apache-spark - SELECT 语句中的 Spark IN/EXISTS 谓词
问题描述
我有以下 Spark SQL 测试查询:
Seq("france").toDF.createOrReplaceTempView("countries")
SELECT CASE WHEN country = 'italy' THEN 'Italy'
ELSE ( CASE WHEN country IN (FROM countries) THEN upperCase(country) ELSE country END )
END AS country FROM users
引发以下错误:
Exception in thread "main" org.apache.spark.sql.AnalysisException:
IN/EXISTS predicate sub-queries can only be used in a Filter
查询的以下部分CASE WHEN country IN (FROM countries)
是其原因。
country IN (FROM countries)
为了在选择条件中进行模拟,Spark SQL 中是否存在任何解决方法?我对纯 SQL 实现感兴趣,而不是通过 API 实现。
解决方案
这是正确的 SQL 查询:
import sparkSession.implicits._
Seq("france").toDF("country").createOrReplaceTempView("countries")
Seq(("user1", "france"), ("user2", "italy"), ("user2", "usa"))
.toDF("user", "country").createOrReplaceTempView("users")
val query =
s"""
|SELECT
| CASE
| WHEN u.country = 'italy' THEN 'Italy'
| ELSE (
| CASE
| WHEN u.country = c.country THEN upper(u.country)
| ELSE u.country
| END
| ) END AS country
|FROM users u
|LEFT JOIN countries c
| ON u.country = c.country
""".stripMargin
sparkSession.sql(query).show()
结果:
+-------+
|country|
+-------+
| FRANCE|
| Italy|
| usa|
+-------+
IN/EXISTS
您只能在谓词中使用 sql 运算符的原因是:投影中的逻辑(CASE-WHEN
在我们的例子中)为从选择返回的数据集中的每一行评估。CASE WHEN country IN (SELECT * FROM countries)
考虑到这一点,对表中的每一行运行等效并不是最好的主意users
。因此,SQL 在语言级别(sql 解析器引擎)上防止了这种情况。
推荐阅读
- python - 列表索引超出范围 - 但它不是
- python - 如何将 pytest.mark 装饰器包装在另一个装饰器中并维护所有属性?
- flutter - Flutter inpute文本字段在失去焦点时丢失文本
- python - Discord Client Bot 没有以正确的方式响应?不和谐.py
- node.js - 尝试使用 gremlin 查询更新属性(如果存在)我收到错误为“找不到名称‘有’”
- r - 如何使用另一个矩阵的列(或行)计算矩阵的每一列(或行)的加权平均值?
- nginx-reverse-proxy - 通过 nginx 暴露多个 docker 服务
- maven - 需要从 mvn 生成的插件中删除“由 maven-plugin-tools 3.5 于 2021-01-20 生成”文本
- c# - 如何在 Windows 和 Linux 上正确存储 .NET Core 非交互式应用程序凭据?
- android - startActivityForResult putExtras being recieved as NULL