2017-10-09 67 views
1

我需要实施星火下面的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| 
+---+---+---+ 

我有落实巢式病例当声明为:

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

回答

3

这里没有嵌套,因此不需要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") 
0

对于更复杂的逻辑,我更喜欢使用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