Spark两个表的结果

时间:2017-01-31 15:07:56

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

我有两个文件/表格如下

File1: 
101,10,20 
102,30,40 
103,50,60 

File2: 
101,10,20 
104,70,80 
103,50,55 

在比较两个文件后,我需要创建新文件:

File3:
102,30,40,D
104,70,80,I
103,50,55,U

其中D为“已删除”,I为“已插入”且U为“已更新”。

我尝试过使用RDD subtract和SparkSQL,但在Spark 1.x中对子查询有限制。

3 个答案:

答案 0 :(得分:0)

一个可能的想法是使用keyBy函数按您所需的密钥对两个RDD进行分组,然后应用不同的操作来计算 D I û

  • D :使用subtractByKey函数计算 file1 中的元素,而不是 file2 ;
  • :用于计算 file2 中的元素的subtractByKey函数,而不是 file1 ;
  • U :使用join函数计算 file1 file2 之间通信中的元素(键!)。

请记住,join函数将与commun中的关键元素一起运行。所以在你的例子中(101,10,20)也将是加入的结果。您必须过滤此结果才能获得包含更改的键。

答案 1 :(得分:0)

我认为您正在寻找类似下面的内容。这里我有两个数据帧df1和df2。 df1是具有键列a1的主数据集,其与具有键列b1的辅助数据集df2进行比较。因此,如果键的字段a2,a3和b2,b3相同,则忽略这些记录。

  • 如果密钥存在于df1而不是df2中,则记录标记为D.
  • 如果密钥存在于df2而不是df1中,则记录标记为I.
  • 如果密钥存在于df1和df2中,则记录将标记为U,但值字段不同。
下面的

是代码段。

from pyspark.sql.functions import udf
from pyspark.sql.types import *
from pyspark.sql import functions as F

input1 = [[101,10,20], [102,30,40], [103,50,60]]
input2 = [[101,10,20], [104,70,80], [103,50,55]]

df1 = sc.parallelize(input1).toDF(schema= StructType([StructField("a1", IntegerType(), False),StructField("a2", IntegerType(), False),StructField("a3", IntegerType(), False)]))
df2 = sc.parallelize(input2).toDF(schema=StructType([StructField("b1", IntegerType(), False),StructField("b2", IntegerType(), False),StructField("b3", IntegerType(), False)]))

joindf = df1.join(df2, [df1.a1 == df2.b1], 'outer').filter(((df1.a2 != df2.b2) | (df1.a3 != df2.b3)) | df1.a1.isNull() | df2.b1.isNull())

def check_row(a1, b1):
    if not a1:
        return 'D'
    elif not b1:
        return 'I'
    else:
        return 'U'

flagger = udf(check_row)
joindf.withColumn("flag", flagger(joindf.a1, joindf.b1)).select(F.when(joindf.a1.isNull(), joindf.b1).otherwise(joindf.a1).alias('a1'),F.when(joindf.a2.isNull(), joindf.b2).otherwise(joindf.a2).alias('a2'),F.when(joindf.a3.isNull(), joindf.b3).otherwise(joindf.a3).alias('a3'),'flag').show()
+---+---+---+----+
| a1| a2| a3|flag|
+---+---+---+----+
|103| 50| 60|   U|
|102| 30| 40|   I|
|104| 70| 80|   D|
+---+---+---+----+

或者如果您更喜欢spark-sql,请使用以下代码段。

sqlContext.registerDataFrameAsTable(df1, 'df1')
sqlContext.registerDataFrameAsTable(df2, 'df2')
sqlContext.sql("""
SELECT 
CASE WHEN a1 IS NULL THEN b1 ELSE a1 END as c1,
CASE WHEN a2 IS NULL THEN b2 ELSE a1 END as c2,
CASE WHEN a3 IS NULL THEN b3 ELSE a1 END as c3,
CASE 
   WHEN a1 IS NULL THEN 'I' 
   WHEN b1 is NULL THEN 'D' 
   ELSE 'U' END as flag
FROM df1 FULL OUTER JOIN df2 ON df1.a1 = df2.b1
WHERE (df1.a2 <> df2.b2 or df1.a3 <> df2.b3) or (df1.a1 is null) or (df2.b1 is null)
""").show()

+---+---+---+----+
| c1| c2| c3|flag|
+---+---+---+----+
|103|103|103|   U|
|102|102|102|   D|
|104| 70| 80|   I|
+---+---+---+----+

答案 2 :(得分:0)

我认为我们可能需要稍微更改spark sql的代码以包含更新条件。

sqlContext.sql("""    
SELECT 

CASE when a1 IS NULL then b1 ELSE a1 END as c1,

CASE when a2 IS NULL then b2 
     when a1 = b1 then b2 
     else a2 END as c2,

CASE when a3 IS NULL then b3 
     when a1 = b1 then b3
     else a3 END as c3,

CASE 
   when a1 IS NULL then 'I' 
   when b1 is NULL then 'D' 
   ELSE 'U' END as flag

FROM df1 FULL OUTER JOIN df2 ON df1.a1 = df2.b1

WHERE (df1.a2 <> df2.b2 or df1.a3 <> df2.b3) or (df1.a1 is null) or (df2.b1 is null)
""").show()