代码之家  ›  专栏  ›  技术社区  ›  alexanoid

Apache Spark SQL查询和数据帧作为参考数据

  •  0
  • alexanoid  · 技术社区  · 7 年前

    我有两个Spark数据帧:

    cities 具有以下列的数据帧:

    city
    -----
    London
    Austin
    

    bigCities 具有以下列的数据帧:

    name
    ------
    London
    Cairo
    

    我需要转换数据帧 城市 并在此添加一个附加的布尔列: bigCity 必须根据以下条件计算此列的值 "cities.city IN bigCities.name"

    我可以通过以下方式(使用静态的BigCities集合)完成此操作:

    cities.createOrReplaceTempView("cities")
    
    var resultDf = spark.sql("SELECT city, CASE WHEN city IN ['London', 'Cairo'] THEN 'Y' ELSE 'N' END AS bigCity FROM cities")
    

    但我不知道如何取代静态的大城市系列 ['London', 'Cairo'] 具有 大城市 查询中的数据帧。我想用 大城市 作为查询中的引用数据。

    请告知如何实现这一目标。

    2 回复  |  直到 7 年前
        1
  •  1
  •   stack0114106    7 年前

    您可以在bigcities表上使用collect_list()。检查这个

    scala> val df_city = Seq(("London"),("Austin")).toDF("city")
    df_city: org.apache.spark.sql.DataFrame = [city: string]
    
    scala> val df_bigCities = Seq(("London"),("Cairo")).toDF("name")
    df_bigCities: org.apache.spark.sql.DataFrame = [name: string]
    
    scala> df_city.createOrReplaceTempView("cities")
    
    scala> df_bigCities.createOrReplaceTempView("bigCities")
    
    scala> spark.sql(" select city, case when array_contains((select collect_list(name) from bigcities),city) then 'Y' else 'N' end as bigCity from cities").show(false)
    +------+-------+
    |city  |bigCity|
    +------+-------+
    |London|Y      |
    |Austin|N      |
    +------+-------+
    
    
    scala>
    

    如果数据集很大,您可以使用收集集,这将更有效。

    scala> spark.sql(" select city, case when array_contains((select collect_set(name) from bigcities),city) then 'Y' else 'N' end as bigCity from cities").show(false)
    +------+-------+
    |city  |bigCity|
    +------+-------+
    |London|Y      |
    |Austin|N      |
    +------+-------+
    
    
    scala>
    
        2
  •  3
  •   Gofrette    7 年前
    val df = cities.join(bigCities, $"name".equalTo($"city"), "leftouter").
                    withColumn("bigCity", when($"name".isNull, "N").otherwise("Y")).
                    drop("name")