2017-10-09 40 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