声明时Spark星际数据帧嵌套情况

时间:2017-10-09 07:27:16

标签: sql apache-spark dataframe apache-spark-sql

我需要在Spark DataFrame

中实现以下SQL逻辑
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|
+---+---+---+

我在语句为:

时实现了嵌套大小写
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语句更进一步,语句有点乱。

在Spark DataFrames中的语句有没有更好的方法来实现嵌套大小写?

3 个答案:

答案 0 :(得分:14)

这里没有嵌套,因此不需要endpoint.name=client-endpoint remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false remote.connections=default remote.connection.default.host=localhost remote.connection.default.port=8080 remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false 。您所需要的只是链接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

请注意,在这一系列条件下,达到“N”结果是不可能的。如果cases.foldLeft(lit(null)) { case (acc, (expr, value)) => when(expr, value).otherwise(acc) } 等于“a”,则第一个子句将捕获它。如果不是,它将无法满足两个谓词并默认为tc。你应该宁愿:

NULL

答案 1 :(得分:2)

对于更复杂的逻辑,我更喜欢使用UDF来提高可读性:

val selectCase = udf((tc: String, amt: String) =>
  if (Seq("a", "b").contains(tc)) "Y"
  else if (tc == "a" && amt.toInt <= 0) "N"
  else null
)


dataset1.withColumn("REASON", selectCase(col("tc"), col("amt")))
  .show

答案 2 :(得分:0)

您只需在数据集上使用selectExpr

dataset1.selectExpr("*", "CASE WHEN tc in ('a') AND amt > 0 THEN 'N' WHEN tc in ('a','b') THEN 'Y' ELSE NULL END
REASON").show()

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

第二个条件应该放在第一个条件之前,因为第一个条件更通用。

  

当tc((a))和amt> 0则为'N'<​​/ p>