避免 Spark SQL 查询的笛卡尔连接

Posted

技术标签:

【中文标题】避免 Spark SQL 查询的笛卡尔连接【英文标题】:Avoid Cartesian Join for the spark SQL query 【发布时间】:2021-04-05 10:05:07 【问题描述】:

我正在尝试根据两个临时表的总数计算 processRate,但我收到错误“检测到逻辑计划之间的 INNER 连接的隐式笛卡尔积”,我什至没有执行连接。我确信可以通过以正确格式重组查询来解决此错误,我需要您的帮助。下面是查询,

spark.sql("""
CREATE OR REPLACE TEMPORARY VIEW final_processRate AS
SELECT
      ((a.total - b.total)/a.total))* 100 AS processRate
FROM
    (select count (*) as total from sales) a,
    (select count (*) as total from sales where status = 'PENDING') b
""")

我在尝试使用查看数据时遇到此错误,

spark.sql("select * from processRate limit 10").show(false)

您能否帮助格式化上述查询以解决此问题并查看final_processRate 的数据?

【问题讨论】:

“我什至没有执行连接” - 为什么您认为这不是连接?我的意思是,你有 FROM a,b - 如果不是加入,还有什么? 另外,您可以为 Spark 启用交叉连接,尽管笛卡尔积通常应该很慢:***.com/a/39000050/4744359 - 对于 Spark 3,它将默认启用,因此您使用的是无论如何,旧版本的 Spark。为什么? 【参考方案1】:

您不需要子查询。只需使用条件聚合:

spark.sql("""
CREATE OR REPLACE TEMPORARY VIEW final_processRate AS
SELECT
    ((count(*) - count(case when status='PENDING' then 1 end)) / count(*)) * 100 AS processRate
FROM sales
""")

然后您可以使用以下命令查询临时视图:

spark.sql("select * from final_processRate")

它应该给你一个上面计算的数字/百分比。

【讨论】:

非常感谢!!有效!!你能解释一下这两个查询之间的区别吗?这对我理解更深层次的逻辑非常有帮助。 您的查询涉及 a 和 b 之间的隐式交叉联接,因为您在 from 中有两个表,导致错误。【参考方案2】:

我会这样写:

select avg(case when status = 'PENDING' then 0.0 else 1 end)
from sales;

这将返回未挂起的行的比例。

【讨论】:

以上是关于避免 Spark SQL 查询的笛卡尔连接的主要内容,如果未能解决你的问题,请参考以下文章

MySQL连接查询

使用笛卡尔连接优化 sql 查询

数据库(MYSQL)连接查询--sql92等值连接

[转]sql语句中出现笛卡尔乘积 SQL查询入门篇

多表联查--00---概述---SQL92,99语法

mysql中的连接查询