Spark2.1.1<SparkSQL中常用四大连接>

本文介绍Spark SQL中的不同连接类型,包括内连接、左外连接、右外连接和全外连接,并通过实例展示了如何使用这些连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境:

Spark 2.1.1 

准备工作

persons.csv:

        +----+--------+---------+--------------+--------+
        |Id_P|LastName|FirstName|       Address|    City|
        +----+--------+---------+--------------+--------+
        |   1|   Adams|     John| Oxford Street|  London|
        |   2|    Bush|   George|  Fifth Avenue|New York|
        |   3|  Carter|   Thomas|Changan Street| Beijing|
        +----+--------+---------+--------------+--------+

orders.csv:


        +----+-------+----+
        |Id_O|OrderNo|Id_P|
        +----+-------+----+
        |   1|  77895|   3|
        |   2|  44678|   3|
        |   3|  22456|   1|
        |   4|  24562|   1|
        |   5|  34764|  65|
        +----+-------+----+

使用到的依赖:

  <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-sql_2.10 -->
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_2.11</artifactId>
            <version>2.1.1</version>
        </dependency>

    </dependencies>

创建SparkSession,读入文件:

    val session = SparkSession.builder().appName("SQL").master("local[2]").getOrCreate()
    val sqlcontext = session.sqlContext
    val orders: DataFrame = session
      .read.option("header", "true")
      .csv(Join.getClass.getResource("/") + "orders.csv")
    val persons: DataFrame = session
      .read.option("header", "true")
      .csv(Join.getClass.getResource("/") + "persons.csv")
       persons.createTempView("Persons")
    orders.createTempView("Orders")

这里写图片描述

1.自然连接(内连接)

作用:选出在两张表中都有的主键的对应的记录

The INNER JOIN keyword selects all rows from both tables as long as there is a match between the columns. If there are records in the "Orders" table that do not have matches in "persons", these orders will not show

1.1自然连接(不用指明要连接的列名)

 sqlcontext.sql("SELECT * FROM Persons NATURAL JOIN Orders").show()

得到的结果:

+----+--------+---------+--------------+-------+----+-------+
|Id_P|LastName|FirstName|       Address|   City|Id_O|OrderNo|
+----+--------+---------+--------------+-------+----+-------+
|   1|   Adams|     John| Oxford Street| London|   4|  24562|
|   1|   Adams|     John| Oxford Street| London|   3|  22456|
|   3|  Carter|   Thomas|Changan Street|Beijing|   2|  44678|
|   3|  Carter|   Thomas|Changan Street|Beijing|   1|  77895|
+----+--------+---------+--------------+-------+----+-------+

1.2 内连接

 sqlcontext.sql("SELECT * FROM Persons INNER JOIN Orders ON Persons.Id_P=Orders.Id_P").show()

得到的结果:

+----+--------+---------+--------------+-------+----+-------+----+
|Id_P|LastName|FirstName|       Address|   City|Id_O|OrderNo|Id_P|
+----+--------+---------+--------------+-------+----+-------+----+
|   1|   Adams|     John| Oxford Street| London|   4|  24562|   1|
|   1|   Adams|     John| Oxford Street| London|   3|  22456|   1|
|   3|  Carter|   Thomas|Changan Street|Beijing|   2|  44678|   3|
|   3|  Carter|   Thomas|Changan Street|Beijing|   1|  77895|   3|
+----+--------+---------+--------------+-------+----+-------+----+

请注意:
sqlcontext.sql("SELECT * FROM Persons JOIN Orders ON Persons.Id_P=Orders.Id_P").show()
这句scala语句的执行结果和内连接是一样的,从写法上省略了Inner


从结果可以看出,内连接需要指明连接列名,而且结果比自然连接多了一列,有两列是相同的

2.左外连接

作用:LEFT JOIN 关键字会从左表 (Persons) 那里返回所有的行,即使在右表 (Orders) 中没有匹配的行。

The LEFT JOIN keyword returns all records from the left table (table1), and the matched records from the right table (table2). The result is NULL from the right side, if there is no match.

scala:

    sqlcontext.sql("SELECT * FROM Persons LEFT JOIN Orders ON Persons.Id_P=Orders.Id_P").show()
    sqlcontext.sql("SELECT * FROM Persons LEFT OUTER JOIN Orders ON Persons.Id_P=Orders.Id_P").show()

上面两句执行的结果都是一样的:

+----+--------+---------+--------------+--------+----+-------+----+
|Id_P|LastName|FirstName|       Address|    City|Id_O|OrderNo|Id_P|
+----+--------+---------+--------------+--------+----+-------+----+
|   1|   Adams|     John| Oxford Street|  London|   4|  24562|   1|
|   1|   Adams|     John| Oxford Street|  London|   3|  22456|   1|
|   2|    Bush|   George|  Fifth Avenue|New York|null|   null|null|
|   3|  Carter|   Thomas|Changan Street| Beijing|   2|  44678|   3|
|   3|  Carter|   Thomas|Changan Street| Beijing|   1|  77895|   3|
+----+--------+---------+--------------+--------+----+-------+----+

3.右外连接

作用:RIGHT JOIN 关键字会从右表 (Orders) 那里返回所有的行,即使在左表 (Persons) 中没有匹配的行。

The RIGHT JOIN keyword returns all records from the right table (table2), and the matched records from the left table (table1). The result is NULL from the left side, when there is no match.

scala:

    sqlcontext.sql("SELECT * FROM Persons RIGHT JOIN Orders ON Persons.Id_P=Orders.Id_P").show()
    sqlcontext.sql("SELECT * FROM Persons RIGHT OUTER JOIN Orders ON Persons.Id_P=Orders.Id_P").show()

以上两句执行结果相同:

+----+--------+---------+--------------+-------+----+-------+----+
|Id_P|LastName|FirstName|       Address|   City|Id_O|OrderNo|Id_P|
+----+--------+---------+--------------+-------+----+-------+----+
|   3|  Carter|   Thomas|Changan Street|Beijing|   1|  77895|   3|
|   3|  Carter|   Thomas|Changan Street|Beijing|   2|  44678|   3|
|   1|   Adams|     John| Oxford Street| London|   3|  22456|   1|
|   1|   Adams|     John| Oxford Street| London|   4|  24562|   1|
|null|    null|     null|          null|   null|   5|  34764|  65|
+----+--------+---------+--------------+-------+----+-------+----+

4.外连接

作用:FULL JOIN 关键字会从左表 (Persons) 和右表 (Orders) 那里返回所有的行。如果 “Persons” 中的行在表 “Orders” 中没有匹配,或者如果 “Orders” 中的行在表 “Persons” 中没有匹配,这些行同样会列出。

The FULL OUTER JOIN keyword return all records when there is a match in either left (table1) or right (table2) table records.

scala:

    sqlcontext.sql("SELECT * FROM Persons FULL JOIN Orders ON Persons.Id_P=Orders.Id_P").show()
    sqlcontext.sql("SELECT * FROM Persons FULL OUTER JOIN Orders ON Persons.Id_P=Orders.Id_P").show()

以上两行代码执行结果相同:

+----+--------+---------+--------------+--------+----+-------+----+
|Id_P|LastName|FirstName|       Address|    City|Id_O|OrderNo|Id_P|
+----+--------+---------+--------------+--------+----+-------+----+
|   3|  Carter|   Thomas|Changan Street| Beijing|   1|  77895|   3|
|   3|  Carter|   Thomas|Changan Street| Beijing|   2|  44678|   3|
|   1|   Adams|     John| Oxford Street|  London|   3|  22456|   1|
|   1|   Adams|     John| Oxford Street|  London|   4|  24562|   1|
|null|    null|     null|          null|    null|   5|  34764|  65|
|   2|    Bush|   George|  Fifth Avenue|New York|null|   null|null|
+----+--------+---------+--------------+--------+----+-------+----+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>untitled</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>first</module> <module>spring5-ioc-xml</module> <module>spring5-ioc-annotation</module> <module>spring5-reflect</module> <module>atguigu-spring</module> <module>spring6-aop</module> <module>spring6-jdbc-tx</module> </modules> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>6.0.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>6.0.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.2</version> </dependency> <dependency> <groupId>jakarta.annotation</groupId> <artifactId>jakarta.annotation-api</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifa
最新发布
04-03
<think>好的,用户想了解如何在Maven的POM文件中配置Spring项目的依赖管理。首先,我需要回忆Maven中的dependencyManagement的作用。根据引用[2],dependencyManagement用于统一管理依赖版本和范围,子模块继承时可以不用指定版本号。而引用[3]提到可以通过<scope>import</scope>来聚合多个pom的dependencyManagement,这可能在Spring Boot项目中用到。 接下来,用户需要具体的例子,可能需要展示一个典型的Spring Boot项目的父POM配置。通常Spring Boot项目会使用spring-boot-starter-parent作为父项目,或者通过dependencyManagement引入Spring Boot的BOM(Bill of Materials)。比如,在父POM的dependencyManagement中导入spring-boot-dependencies,这样所有子模块的Spring依赖就可以省略版本号。 然后,用户可能想知道如何管理不同模块的依赖,比如web、data-jpa等。需要展示如何在子模块的dependencies中添加starter依赖,比如spring-boot-starter-web,并说明由于父POM的dependencyManagement,这里不需要写版本。 另外,引用[1]提到dependencies标签用于管理依赖,而dependencyManagement是集中管理版本。需要区分两者的不同,确保用户理解何时使用哪个部分。 还要注意是否需要处理多模块项目,引用[3]提到的聚合工程可能需要使用import scope来合并多个依赖管理,这在复杂项目中可能会有用。例如,如果项目同时需要Spring Cloud的依赖管理,可以通过import scope引入。 最后,确保提供的示例代码正确,符合Maven语法,并且注释清晰。同时,生成的相关问题需要涵盖用户可能进一步询问的内容,比如版本冲突解决、多模块配置等。</think>### Maven项目配置及Spring依赖管理示例 在Maven中管理Spring依赖时,通常结合`<dependencyManagement>`实现版本统一控制。以下是典型配置步骤: --- #### 1. **父POM中定义Spring Boot依赖管理** 通过`<dependencyManagement>`导入Spring Boot官方提供的BOM(Bill of Materials),自动管理所有Spring Boot相关依赖的版本: ```xml <project> <dependencyManagement> <dependencies> <!-- 引入Spring Boot官方BOM --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.1.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project> ``` - `<scope>import</scope>`表示继承目标POM中定义的依赖管理规则[^3] - 子模块中引用Spring依赖时**无需指定版本号** --- #### 2. **子模块添加具体依赖** 在需要Spring功能的模块中,直接声明starter依赖: ```xml <dependencies> <!-- Web模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 数据访问模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> </dependencies> ``` --- #### 3. **多模块依赖管理(可选)** 对于需要合并多个BOM的复杂项目: ```xml <dependencyManagement> <dependencies> <!-- 同时引入Spring Cloud和Spring Boot的BOM --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2022.0.1</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.1.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ``` - 多个BOM的依赖版本会根据声明顺序合并 --- #### 4. **依赖范围控制示例** 通过`<scope>`定义依赖作用域: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> ``` - `test`表示该依赖仅在测试阶段有效[^2] --- ### 关键概念对比 | 配置项 | 作用域 | 特点 | |---------------------|----------------|----------------------------------------------------------------------| | `<dependencies>` | 当前模块 | 直接引入依赖,版本号必须显式声明 | | `<dependencyManagement>` | 全局管理 | 仅定义版本和范围,子模块引用时可省略版本号[^2] |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值