Spark Dataframe 嵌套 Case When 语句

新手上路,请多包涵

我需要在 Spark 中实现以下 SQL 逻辑 DataFrame

 SELECT KEY,
    CASE WHEN tc in ('a','b') THEN 'Y'
         WHEN tc in ('a') AND amt > 0 THEN 'N'
         ELSE NULL END REASON,
FROM dataset1;

我的输入 DataFrame 如下:

 val dataset1 = Seq((66, "a", "4"), (67, "a", "0"), (70, "b", "4"), (71, "d", "4")).toDF("KEY", "tc", "amt")

dataset1.show()

 +---+---+---+
|KEY| tc|amt|
+---+---+---+
| 66|  a|  4|
| 67|  a|  0|
| 70|  b|  4|
| 71|  d|  4|
+---+---+---+

我已经将嵌套的 case when 语句实现为:

 dataset1.withColumn("REASON", when(col("tc").isin("a", "b"), "Y")
  .otherwise(when(col("tc").equalTo("a") && col("amt").geq(0), "N")
    .otherwise(null))).show()

 +---+---+---+------+
|KEY| tc|amt|REASON|
+---+---+---+------+
| 66|  a|  4|     Y|
| 67|  a|  0|     Y|
| 70|  b|  4|     Y|
| 71|  d|  4|  null|
+---+---+---+------+

如果嵌套的 when 语句更进一步,则上述逻辑与“otherwise”语句的可读性有点混乱。

当 Spark DataFrames 中的语句时,有没有更好的方法来实现嵌套案例?

原文由 RaAm 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
1 个回答

这里没有嵌套,因此不需要 otherwise 。您需要的只是链式 when

 import spark.implicits._

when($"tc" isin ("a", "b"), "Y")
  .when($"tc" === "a" && $"amt" >= 0, "N")

ELSE NULL 是隐含的,因此您可以完全省略它。

您使用的模式更适用于 folding 在数据结构上:

 val cases = Seq(
  ($"tc" isin ("a", "b"), "Y"),
  ($"tc" === "a" && $"amt" >= 0, "N")
)

其中 when - otherwise 自然遵循递归模式,而 null 提供基本情况。

 cases.foldLeft(lit(null)) {
  case (acc, (expr, value)) => when(expr, value).otherwise(acc)
}

请注意,在这一系列条件下,不可能达到“N”结果。如果 tc 等于“a”,它将被第一个子句捕获。如果不是,它将无法同时满足谓词并默认为 NULL 。您应该:

 when($"tc" === "a" && $"amt" >= 0, "N")
 .when($"tc" isin ("a", "b"), "Y")

原文由 zero323 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进