【问题标题】:SQL: table to key-value tableSQL:表到键值表
【发布时间】:2020-04-21 08:30:08
【问题描述】:

我在 HIVE 中有这样的表:

A    | B   | C  | value
key1 |NULL|NULL| v1
NULL | key2  |NULL| v2
NULL |NULL| key3  | v3
NULL | key4  |NULL| v4

将它转换为像这样的一些键值表的最简单方法是什么:

key_type | key_value | value
A | key1 | v1
B | key2 | v2
C | key3 | v3
B | key4 | v4

使用 Hive-SQL 或 Spark Dataframe 转换 (PySpark)? 感谢您的帮助。

【问题讨论】:

    标签: sql pyspark hql hiveql


    【解决方案1】:

    使用pyspark,可以在过滤需要的列后使用greatest,当列值不为空时返回列名:

    import pyspark.sql.functions as F
    
    cols = [i for i in df.columns if i!='value'] #['A','B','C']
    
    output = df.select(F.greatest(*[F.when(F.col(i).isNotNull(),i)
                                 for i in cols]).alias("key_type")
                   ,F.greatest(*[F.col(i) for i in cols]).alias("key_Value"),"value")
    

    output.show()
    
    +--------+---------+-----+
    |key_type|key_Value|value|
    +--------+---------+-----+
    |       A|     key1|   v1|
    |       B|     key2|   v2|
    |       C|     key3|   v3|
    |       B|     key4|   v4|
    +--------+---------+-----+
    

    【讨论】:

    • 我喜欢你在key_type 列中使用greatest 的方式
    • @MohammadMurtazaHashmi 谢谢 :-) 你知道从每一行获取第一个非空值的任何其他方法吗?
    • 我的第一个想法是使用coalesce,我在下面发布了供您查看。
    【解决方案2】:

    另一种方法。使用 pyspark.sql.functions.coalesce

    from pyspark.sql import functions as F
    
    df.withColumn("key",F.coalesce(*[(F.when(F.col(x).isNotNull(),F.array(F.lit(x),F.col(x)))).alias(x)\
                                     for x in df.columns if x!='value']))\
      .select((F.col("key")[0]).alias("key_type"),(F.col("key")[1]).alias("key_value"),F.col("value")).show()
    
    #+--------+---------+-----+
    #|key_type|key_value|value|
    #+--------+---------+-----+
    #|       A|     key1|   v1|
    #|       B|     key2|   v2|
    #|       C|     key3|   v3|
    #|       B|     key4|   v4|
    #+--------+---------+-----+
    

    【讨论】:

      【解决方案3】:

      你可以使用union all:

      select t.key_type, t.key_value, t.value
      from ( (select 'a' as key_type, a as key_value, value from t) union all
             (select 'b' as key_type, b as key_value, value from t) union all
             (select 'c' as key_type, c as key_value, value from t) 
           ) t
      where t.key_type is not null
      order by t.value;
      

      【讨论】:

        猜你喜欢
        • 2011-05-13
        • 1970-01-01
        • 1970-01-01
        • 2019-05-04
        • 1970-01-01
        • 2021-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多