可以将原始sql字符串转换为Dataframe。但是否也有可能反过来,即获取(派生的)sparkDataframe的查询逻辑的sql表示?
// Source data
val a = Seq(7, 8, 9, 7, 8, 7).toDF("foo")
// Query using DataFrame functions
val b = a.groupBy($"foo").agg(count("*") as "occurrences").orderBy($"occurrences")
b.show()
// Convert a SQL string into a DataFrame
val sqlString = "SELECT foo, count(*) as occurrences FROM a GROUP BY foo ORDER BY occurrences"
a.createOrReplaceTempView("a")
val c = currentSparkSession.sql(sqlString)
c.show()
// "Convert" a DataFrame into a SQL string
b.toSQLString() // Error: This function does not exist.
2条答案
按热度按时间px9o7tmv1#
无法将Dataframe“转换”为sql字符串,因为spark不知道如何编写sql查询,也不需要这样做。
我发现回忆一下spark如何处理Dataframe代码或sql查询是很有用的。这是由spark的catalyst optimizer完成的,它经历了四个转型阶段,如下所示:
在第一阶段(分析),sparksql引擎为sql或dataframe查询生成一个抽象语法树(ast)。此树是catalyst中的主要数据类型(请参阅白皮书spark sql中的第4.1节:spark中的关系数据处理),用于创建逻辑计划并最终创建物理计划。如果你使用
explain
spark提供的api。虽然我很清楚你所说的“可以将原始sql字符串转换为Dataframe”是什么意思,但我想更精确一点是有帮助的。我们不会将一个sql字符串(因此您自己在这个词周围加引号)转换成一个Dataframe,但是您应用了您的sql知识,因为这是spark可以解析的语法来理解您的意图。此外,您不能只键入任何sql查询,因为在分析阶段与目录进行比较时,这仍然可能失败。因此,sql字符串只是关于spark如何允许您给出指令的协议。然后对这个sql查询进行解析,将其转换为ast(如上所述),并在完成其他三个阶段之后生成基于rdd的代码。通过
sql
api返回一个Dataframe,而您可以使用df.rdd
.总的来说,spark不需要将任何代码,特别是任何Dataframe代码编写成sql语法,然后就可以从spark中删除。ast是内部抽象,spark不需要先将Dataframe代码转换为sql查询,而直接将Dataframe代码转换为ast。
nimxete22#
不可以。没有方法可以从Dataframe获取sql查询。您必须通过查看所有过滤器并选择用于创建Dataframe的过滤器来创建查询。