• PySpark 各种姿势的join连接


    参考:https://sparkbyexamples.com/pyspark/pyspark-join-explained-with-examples/

    1. PySpark 连接语法

    PySpark SQL 连接具有以下语法,可以直接从 DataFrame 访问。

    
    join(self, other, on=None, how=None)
    

    join()操作接受如下参数并返回DataFrame。

    • 参数 other:连接的右侧
    • 参数 on:连接列名称的字符串
    • 参数如何:默认inner。必须是innercrossouterfullfull_outerleftleft_outerrightright_outerleft_semi, 和之一left_anti

    您还可以通过在 DataFrame 上添加where()filter()方法来编写 Join 表达式,并且可以在多个列上进行 Join。

    2. PySpark 连接类型

    以下是 PySpark 支持的不同连接类型。

    Join String Equivalent SQL Join
    inner INNER JOIN
    outer, full, fullouter, full_outer FULL OUTER JOIN
    left, leftouter, left_outer LEFT JOIN
    right, rightouter, right_outer RIGHT JOIN
    cross  
    anti, leftanti, left_anti  
    semi, leftsemi, left_semi


    PySpark 连接类型

    在我们进入 PySpark SQL Join 示例之前,首先,让我们创建一个"emp""dept" DataFrames。在这里,列"emp_id"在 emp 上"dept_id"是唯一的,并且在 dept 数据集上是唯一的,并且来自 emp 的 emp_dept_id 具有对 dept 数据集上的 dept_id 的引用。

    
    emp = [(1,"Smith",-1,"2018","10","M",3000), \
        (2,"Rose",1,"2010","20","M",4000), \
        (3,"Williams",1,"2010","10","M",1000), \
        (4,"Jones",2,"2005","10","F",2000), \
        (5,"Brown",2,"2010","40","",-1), \
          (6,"Brown",2,"2010","50","",-1) \
      ]
    empColumns = ["emp_id","name","superior_emp_id","year_joined", \
           "emp_dept_id","gender","salary"]
    
    empDF = spark.createDataFrame(data=emp, schema = empColumns)
    empDF.printSchema()
    empDF.show(truncate=False)
    
    dept = [("Finance",10), \
        ("Marketing",20), \
        ("Sales",30), \
        ("IT",40) \
      ]
    deptColumns = ["dept_name","dept_id"]
    deptDF = spark.createDataFrame(data=dept, schema = deptColumns)
    deptDF.printSchema()
    deptDF.show(truncate=False)
    

    这会将“emp”和“dept”DataFrame 打印到控制台。请参阅下面有关如何创建spark对象的完整示例。

    
    Emp Dataset
    +------+--------+---------------+-----------+-----------+------+------+
    |emp_id|name    |superior_emp_id|year_joined|emp_dept_id|gender|salary|
    +------+--------+---------------+-----------+-----------+------+------+
    |1     |Smith   |-1             |2018       |10         |M     |3000  |
    |2     |Rose    |1              |2010       |20         |M     |4000  |
    |3     |Williams|1              |2010       |10         |M     |1000  |
    |4     |Jones   |2              |2005       |10         |F     |2000  |
    |5     |Brown   |2              |2010       |40         |      |-1    |
    |6     |Brown   |2              |2010       |50         |      |-1    |
    +------+--------+---------------+-----------+-----------+------+------+
    
    Dept Dataset
    +---------+-------+
    |dept_name|dept_id|
    +---------+-------+
    |Finance  |10     |
    |Marketing|20     |
    |Sales    |30     |
    |IT       |40     |
    +---------+-------+
    

    3. PySpark 内连接数据框

    Inner join 是 PySpark 中的默认连接,它最常被使用。emp这会在键列上连接两个数据集,其中键与从两个数据集 ( & dept) 中删除的行不匹配。

    
    empDF.join(deptDF,empDF.emp_dept_id ==  deptDF.dept_id,"inner") \
         .show(truncate=False)
    

    当我们对数据集应用内连接时,它会从“”数据集中删除“ emp_dept_id”50,从“ emp”数据集中删除“ dept_id”30 dept(因为二者没有交集)。下面是上述 Join 表达式的结果。

    
    +------+--------+---------------+-----------+-----------+------+------+---------+-------+
    |emp_id|name    |superior_emp_id|year_joined|emp_dept_id|gender|salary|dept_name|dept_id|
    +------+--------+---------------+-----------+-----------+------+------+---------+-------+
    |1     |Smith   |-1             |2018       |10         |M     |3000  |Finance  |10     |
    |2     |Rose    |1              |2010       |20         |M     |4000  |Marketing|20     |
    |3     |Williams|1              |2010       |10         |M     |1000  |Finance  |10     |
    |4     |Jones   |2              |2005       |10         |F     |2000  |Finance  |10     |
    |5     |Brown   |2              |2010       |40         |      |-1    |IT       |40     |
    +------+--------+---------------+-----------+-----------+------+------+---------+-------+
    

    4. PySpark 全外连接

    Outeraka fullfullouterjoin 返回两个数据集中的所有行,其中 join 表达式不匹配它在相应的记录列上返回 null 。

    
    empDF.join(deptDF,empDF.emp_dept_id ==  deptDF.dept_id,"outer") \
        .show(truncate=False)
    empDF.join(deptDF,empDF.emp_dept_id ==  deptDF.dept_id,"full") \
        .show(truncate=False)
    empDF.join(deptDF,empDF.emp_dept_id ==  deptDF.dept_id,"fullouter") \
        .show(truncate=False)
    

    从我们的“ emp”数据集的“ emp_dept_id”中,值为 50 的“ ”上没有记录,dept因此 dept 列有 null ,“ dept_id” 30 在“ ”中没有记录,emp因此您在 emp 列上看到 null(直观理解,就是并集) 。下面是上述 Join 表达式的结果。

    
    +------+--------+---------------+-----------+-----------+------+------+---------+-------+
    |emp_id|name    |superior_emp_id|year_joined|emp_dept_id|gender|salary|dept_name|dept_id|
    +------+--------+---------------+-----------+-----------+------+------+---------+-------+
    |2     |Rose    |1              |2010       |20         |M     |4000  |Marketing|20     |
    |5     |Brown   |2              |2010       |40         |      |-1    |IT       |40     |
    |1     |Smith   |-1             |2018       |10         |M     |3000  |Finance  |10     |
    |3     |Williams|1              |2010       |10         |M     |1000  |Finance  |10     |
    |4     |Jones   |2              |2005       |10         |F     |2000  |Finance  |10     |
    |6     |Brown   |2              |2010       |50         |      |-1    |null     |null   |
    |null  |null    |null           |null       |null       |null  |null  |Sales    |30     |
    +------+--------+---------------+-----------+-----------+------+------+---------+-------+
    

    5. PySpark 左外连接

    Leftaka Leftouterjoin 返回左侧数据集中的所有行,无论在右侧数据集上找到匹配,当连接表达式不匹配时,它为该记录分配 null 并从右侧删除未找到匹配的记录。

    
      empDF.join(deptDF,empDF.emp_dept_id ==  deptDF.dept_id,"left")
        .show(truncate=False)
      empDF.join(deptDF,empDF.emp_dept_id ==  deptDF.dept_id,"leftouter")
        .show(truncate=False)
    

    从我们的数据集中,“ emp_dept_id” 5o 在“ ”数据集上没有记录,因此,该记录在“ ”列(dept_name 和 dept_id)dept上包含空值。dept和“ ”数据集中的“ dept_id” 30 从dept结果中删除。下面是上述 Join 表达式的结果。

    
    +------+--------+---------------+-----------+-----------+------+------+---------+-------+
    |emp_id|name    |superior_emp_id|year_joined|emp_dept_id|gender|salary|dept_name|dept_id|
    +------+--------+---------------+-----------+-----------+------+------+---------+-------+
    |1     |Smith   |-1             |2018       |10         |M     |3000  |Finance  |10     |
    |2     |Rose    |1              |2010       |20         |M     |4000  |Marketing|20     |
    |3     |Williams|1              |2010       |10         |M     |1000  |Finance  |10     |
    |4     |Jones   |2              |2005       |10         |F     |2000  |Finance  |10     |
    |5     |Brown   |2              |2010       |40         |      |-1    |IT       |40     |
    |6     |Brown   |2              |2010       |50         |      |-1    |null     |null   |
    +------+--------+---------------+-----------+-----------+------+------+---------+-------+
    

    更多见原文

    9. PySpark 自加入

    没有自连接,连接是不完整的,虽然没有可用的自连接类型,但我们可以使用上述任何一种连接类型将 DataFrame 连接到自身。下面的示例使用inner自联接。

    
    empDF.alias("emp1").join(empDF.alias("emp2"), \
        col("emp1.superior_emp_id") == col("emp2.emp_id"),"inner") \
        .select(col("emp1.emp_id"),col("emp1.name"), \
          col("emp2.emp_id").alias("superior_emp_id"), \
          col("emp2.name").alias("superior_emp_name")) \
       .show(truncate=False)
    

    在这里,我们将emp数据集与自身结合起来,以找出优秀的emp_idname为所有员工服务。

    
    +------+--------+---------------+-----------------+
    |emp_id|name    |superior_emp_id|superior_emp_name|
    +------+--------+---------------+-----------------+
    |2     |Rose    |1              |Smith            |
    |3     |Williams|1              |Smith            |
    |4     |Jones   |2              |Rose             |
    |5     |Brown   |2              |Rose             |
    |6     |Brown   |2              |Rose             |
    +------+--------+---------------+-----------------+
    

    4. 使用 SQL 表达式

    由于 PySpark SQL 支持原生 SQL 语法,我们还可以在 DataFrames 上创建临时表后编写连接操作,并在spark.sql().

    
    empDF.createOrReplaceTempView("EMP")
    deptDF.createOrReplaceTempView("DEPT")
    
    joinDF = spark.sql("select * from EMP e, DEPT d where e.emp_dept_id == d.dept_id") \
      .show(truncate=False)
    
    joinDF2 = spark.sql("select * from EMP e INNER JOIN DEPT d ON e.emp_dept_id == d.dept_id") \
      .show(truncate=False)
    

    5. PySpark SQL Join 多个 DataFrames

    当您需要连接两个以上的表时,您可以在 DataFrame 上创建临时视图后使用 SQL 表达式,或者使用连接操作的结果与另一个 DataFrame 连接,例如链接它们。例如

    
    df1.join(df2,df1.id1 == df2.id2,"inner") \
       .join(df3,df1.id1 == df3.id3,"inner")
    

    示例可在GitHub项目中获得以供参考。

    结论

    在本 PySpark SQL 教程中,您学习了可以使用 DataFrame 的join()功能连接两个或多个 DataFrame,Join 类型语法、用法和 PySpark 示例(Spark with Python),我还建议您阅读优化 SQL 连接以了解对连接的性能影响。

  • 相关阅读:
    ibatis 中isNull, isNotNull与isEmpty, isNotEmpty区别
    关于异常Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
    php 利用fsockopen GET/POST 提交表单及上传文件
    php发送get、post请求获取内容的几种方法
    修改WampServer的默认端口
    SQL Server2008附加数据库之后显示为只读时解决方法
    Linux一键安装web环境全攻略(阿里云服务器)
    如何从Windows远程上传文件到Linux(例如CentOS 7)
    在CentOS上搭建PHP服务器环境
    linux(系统centos6.5)常用命令总结
  • 原文地址:https://www.cnblogs.com/bonelee/p/16578929.html
Copyright © 2020-2023  润新知