使用Spark Dataframe在Hive分区中缺少日期的前导零

时间:2016-02-08 06:15:31

标签: java hadoop apache-spark hive apache-spark-sql

我正在为Spark Dataframe添加一个分区列。新列包含年月和日。 我的数据框中有一个时间戳列。

DataFrame dfPartition = df.withColumn("year", df.col("date").substr(0, 4));
dfPartition = dfPartition.withColumn("month", dfPartition.col("date").substr(6, 2));
dfPartition =  dfPartition.withColumn("day", dfPartition.col("date").substr(9, 2));

当我输出数据帧时,我可以看到正确的列值,例如:2016 01 08

但是当我将此数据框导出到像

这样的hive表时
dfPartition.write().partitionBy("year", "month","day").mode(SaveMode.Append).saveAsTable("testdb.testtable");

我看到生成的目录结构错过了前导零。 我试图将列转换为String但不起作用。

是否有办法在hive分区中捕获两位数的日期/月

由于

2 个答案:

答案 0 :(得分:1)

Spark documentation,分区列类型推断是默认启用的功能。由于OP字符串值可以解释为int型,因此它们按原样转换。如果这在整个Spark会话中是不可取的,则可以通过将相应的spark配置属性设置为false来禁用它:

SparkSession.builder.config("spark.sql.sources.partitionColumnTypeInference.enabled", value = false)

或通过使用SQL运行相应的SET key=value命令。否则,可以按照J.Doe的建议,在带有相应Spark-native format-string function的列级别上单独抵消它。

答案 1 :(得分:0)

请参阅Add leading zeros to Columns in a Spark Data Frame

您可以在此答案中看到如何添加前导0的答案:

 val df2 = df
        .withColumn("month", format_string("%02d", $"month"))

我使用下面的代码段在代码中尝试了此方法,并且有效!

            .withColumn("year", year(col("my_time")))
            .withColumn("month", format_string("%02d",month(col("my_time")))) //pad with leading 0's
            .withColumn("day", format_string("%02d",dayofmonth(col("my_time")))) //pad with leading 0's
            .withColumn("hour", format_string("%02d",hour(col("my_time")))) //pad with leading 0's
            .writeStream
            .partitionBy("year", "month", "day", "hour")