将行转置为列

时间:2019-10-15 12:33:10

标签: sql apache-spark-sql pyspark-sql

我需要将行转置为列。有2个表格(如下所示)。 product表中的每个记录与0表中的12product_segment记录匹配。产品可以有2种类型-HOSAMB。要求是根据此产品类型,在目标中将“细分”值填充到其对应的2列(对于HOS为1,对于AM为1)。

基于源中存在的相应product-type记录,在目标中填充该HOS_segment或AMB_segment的值。如果同时存在两种记录类型,则在输出中填充两个字段,否则填充现有的一个。

假设表为:

产品:

product_id | eff_date
12345 | 10/01/2018
75852 | 22/05/2018
33995 | 15/02/2019

product_segment:

product_id | segment | type
12345 | KA | HOS
12345 | HM | AMB
75852 | GB | HOS
33995 | HD | AMB

预期输出:

product_id | eff_date | HOS_segment | AMB_segment
12345 | 10/01/2018 | KA | HM
75852 | 22/05/2018 | GB | Null
33995 | 15/02/2019 | Null | HD

对于product 12345,HOS和AMB记录都存在,因此在输出中,这两个列均填充有其对应的段。
对于product 75852,仅存在HOS记录,因此,将填充HOS_segment,而AMB_segment将为Null
最后,product 33995恰好相反。填充AMB_segment,但填充HOS_segment为空

谁能帮我解决这个问题

2 个答案:

答案 0 :(得分:1)

  

而不是使用联接,在这里我建议使用透视图进行单个联接。这是代码片段。

>>> import pyspark.sql.functions as F
>>> df1= spark.createDataFrame([[12345,"10/01/2018"],[75852,"10/01/2018"],[33995,"10/01/2018"]],["product_id","eff_date"])
>>> df1.show()
+----------+----------+                                                         
|product_id|  eff_date|
+----------+----------+
|     12345|10/01/2018|
|     75852|10/01/2018|
|     33995|10/01/2018|
+----------+----------+

>>> df2 = spark.createDataFrame([[12345,"KA","HOS"],[12345,"HM","AMB"],[75852,"GB","HOS"],[33995,"HD","AMB"]],["product_id","Segment","type"])
>>> df2.show()

+----------+-------+----+
|product_id|Segment|type|
+----------+-------+----+
|     12345|     KA| HOS|
|     12345|     HM| AMB|
|     75852|     GB| HOS|
|     33995|     HD| AMB|
+----------+-------+----+

>>> df1.join(df2,df1.product_id ==df2.product_id,"inner").groupBy(df2.product_id,df1.eff_date).pivot("type").agg(F.first(df2.Segment)).show()
+----------+----------+----+----+
|product_id|  eff_date| AMB| HOS|
+----------+----------+----+----+
|     12345|10/01/2018|  HM|  KA|
|     33995|10/01/2018|  HD|null|
|     75852|10/01/2018|null|  GB|
+----------+----------+----+----+
  

Spark-sql 2.4 +

>>> df1.registerTempTable("df1_temp")
>>> df2.registerTempTable("df2_temp")
>>> spark.sql("select * from(select a.*,b.segment,b.type from df1_temp a inner join df2_temp b on a.product_id =b.product_id) PIVOT( first(segment) for type in ('HOS' HOS_segment,'AMB' AMB_Segment )) " ).show()
+----------+----------+-----------+-----------+
|product_id|  eff_date|HOS_segment|AMB_Segment|
+----------+----------+-----------+-----------+
|     12345|10/01/2018|         KA|         HM|
|     33995|10/01/2018|       null|         HD|
|     75852|10/01/2018|         GB|       null|
+----------+----------+-----------+-----------+

我希望它将对您有所帮助。如果您有与此相关的任何问题,请告诉我。

答案 1 :(得分:0)

您可以将联接与已过滤的细分表一起使用。

import pyspark.sql.functions as F

product \
.join(product_segment.where("type = 'HOS'").select("product_id", F.col("segment").alias("HOS_segment")), "product_id", "left_outer") \
.join(product_segment.where("type = 'AMB'").select("product_id", F.col("segment").alias("AMB_segment")), "product_id", "left_outer")