代码之家  ›  专栏  ›  技术社区  ›  Georg Heiler

当列[重复]时动态触发嵌套大小写

  •  0
  • Georg Heiler  · 技术社区  · 6 年前

    我需要在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;
    

    我的投入 如下所示:

    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中有没有更好的方法实现嵌套case-when语句 DataFrames

    0 回复  |  直到 6 年前
        1
  •  19
  •   zero323 little_kid_pea    8 年前

    这里没有巢穴,因此没有必要 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")
    )
    

    哪里 什么时候 - 自然遵循递归模式 null 提供基本情况。

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

    tc 等于“a”,它将被第一个子句捕获。否则,它将无法同时满足谓词和 NULL . 你应该:

    when($"tc" === "a" && $"amt" >= 0, "N")
     .when($"tc" isin ("a", "b"), "Y")
    
        2
  •  2
  •   Raphael Roth    8 年前

    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
    
        3
  •  0
  •   PoojanKothari    6 年前

    您只需在数据集上使用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|
    +---+---+---+------+
    

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

    推荐文章