我的问题与此问题非常相似:Apache Spark SQL issue : java.lang.RuntimeException: [1.517] failure: identifier expected但我无法弄清问题在哪里。我使用SQLite作为数据库后端。连接和简单的选择语句可以正常工作。
违规行:
val df = tableData.selectExpr(tablesMap(t).toSeq:_*).map(r => myMapFunc(r))
tablesMap包含表名作为键,字符串数组作为表达式。印刷,阵列看起来像这样:
WrappedArray([My Col A], [ColB] || [Col C] AS ColB)
表名也包含在方括号中,因为它包含空格。我得到的例外:
Exception in thread "main" java.lang.RuntimeException: [1.1] failure: identifier expected
我已经确定不使用任何Spark Sql关键字。在我看来,这个代码失败有两个可能的原因:1)我以某种方式处理列名中的空格错误。 2)我处理串联错误。
我正在使用类似CSV的资源文件,其中包含我想要在我的表上评估的表达式。除了这个文件,我想允许用户在运行时指定其他表及其各自的列表达式。该文件如下所示:
TableName,`Col A`,`ColB`,CONCAT(`ColB`, ' ', `Col C`)
在此,这不起作用。不过我想重用这个文件,当然是修改过的。我的想法是将列与字符串数组中的表达式(如现在)映射到一系列火花列。 (这是我能想到的唯一解决方案,因为我想避免仅为这一个功能引入所有的hive dependecies。)我将为我的表达式引入一个小语法来标记带有{{1}的原始列名称以及$
和concat
等函数的一些关键字。但我怎么能这样做?我试过这样的事情,但它甚至远离编译。
as
答案 0 :(得分:3)
一般来说,使用包含空格的名称会引发问题,但用反引号替换方括号应该可以解决问题:
val df = sc.parallelize(Seq((1,"A"), (2, "B"))).toDF("f o o", "b a r")
df.registerTempTable("foo bar")
df.selectExpr("`f o o`").show
// +-----+
// |f o o|
// +-----+
// | 1|
// | 2|
// +-----+
sqlContext.sql("SELECT `b a r` FROM `foo bar`").show
// +-----+
// |b a r|
// +-----+
// | A|
// | B|
// +-----+
对于连接,您必须使用concat
函数:
df.selectExpr("""concat(`f o o`, " ", `b a r`)""").show
// +----------------------+
// |'concat(f o o, ,b a r)|
// +----------------------+
// | 1 A|
// | 2 B|
// +----------------------+
但它在Spark 1.4.0中需要HiveContext
。
实际上,我只需在加载数据后重命名列
df.toDF("foo", "bar")
// org.apache.spark.sql.DataFrame = [foo: int, bar: string]
并使用函数而不是表达式字符串(concat
函数仅在Spark> = 1.5.0中可用,对于1.4及更早版本,您需要UDF):
import org.apache.spark.sql.functions.concat
df.select($"f o o", concat($"f o o", lit(" "), $"b a r")).show
// +----------------------+
// |'concat(f o o, ,b a r)|
// +----------------------+
// | 1 A|
// | 2 B|
// +----------------------+
还有concat_ws
函数,它将separator作为第一个参数:
df.selectExpr("""concat_ws(" ", `f o o`, `b a r`)""")
df.select($"f o o", concat_ws(" ", $"f o o", $"b a r"))