我花了相当长的时间编写多个SQL查询,这些查询以前用于获取各种R
脚本的数据。这就是它的工作原理
sqlContent = readSQLFile("file1.sql")
sqlContent = setSQLVariables(sqlContent, variables)
results = executeSQL(sqlContent)
线索是,对于某些查询,需要先前查询的结果 - 为什么在数据库本身中创建VIEW
并不能解决此问题。有了Spark 2.0
我已经找到了一种方法来做到这一点
// create a dataframe using a jdbc connection to the database
val tableDf = spark.read.jdbc(...)
var tempTableName = "TEMP_TABLE" + java.util.UUID.randomUUID.toString.replace("-", "").toUpperCase
var sqlQuery = Source.fromURL(getClass.getResource("/sql/" + sqlFileName)).mkString
sqlQuery = setSQLVariables(sqlQuery, sqlVariables)
sqlQuery = sqlQuery.replace("OLD_TABLE_NAME",tempTableName)
tableDf.createOrReplaceTempView(tempTableName)
var data = spark.sql(sqlQuery)
但以我的拙见,这是非常繁琐的。此外,更复杂的查询,例如包含子查询分解的查询目前不起作用。有没有更健壮的方法,比如使用 filter($"")
、.select($"")
等将 SQL 代码重新实现到Spark.SQL
代码中。
总体目标是获取多个 org.apache.spark.sql.DataFrame
,每个查询表示一个以前的 SQL 查询的结果(总是几个 JOIN
、WITH
s 等(。因此,n
导致n
DataFrame
的查询。
有没有比提供的两个更好的选择?
设置: Hadoop v.2.7.3
, Spark 2.0.0
, Intelli J IDEA 2016.2
, Scala 2.11.8
, Win7 工作站上的测试集群
不是特别清楚您的要求是什么,但我认为您是在说您有这样的查询:
SELECT * FROM people LEFT OUTER JOIN places ON ...
SELECT * FROM (SELECT * FROM people LEFT OUTER JOIN places ON ...) WHERE age>20
并且您希望将其声明并有效地执行为
SELECT * FROM people LEFT OUTER JOIN places ON ...
SELECT * FROM <cachedresult> WHERE age>20
为了实现这一点,我将增强输入文件,以便每个sql语句都有一个关联的表名,结果将存储在其中。
例如
PEOPLEPLACEStSELECT * FROM people LEFT OUTER JOIN places ON ...
ADULTS=SELECT * FROM PEOPLEPLACES WHERE age>18
然后在循环中执行,例如
parseSqlFile().foreach({case (name, query) => {
val data: DataFrame = execute(query)
data.createOrReplaceTempView(name)
}
请确保按顺序声明查询,以便创建所有必需的表。其他人做更多的解析和按依赖项排序。
在RDMS中,我将这些表称为物化视图。 即对其他数据(如视图(的转换,但缓存结果以供以后重用。