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|
+----+--------+---------+--------------+--------+----+-------+----+
<think>好的,我现在需要解决用户在Maven项目中遇到的Jakarta Annotation依赖版本2.1.1报错的问题。首先,用户提到了引用[1]中的依赖配置,可能他们在使用这个版本时遇到了错误。我需要先了解常见的导致依赖错误的原因,比如版本不存在、与其他依赖冲突,或者仓库配置问题。 首先,我应该检查Jakarta Annotation API的2.1.1版本是否真的存在。访问Maven中央仓库网站,搜索jakarta.annotation-api,查看可用的版本列表。如果2.1.1不存在,那用户可能是错误地引用了这个版本号,需要更正为正确的版本。例如,可能用户记错了,实际最新版本是2.1.0或其他。 接下来,如果版本号正确,可能是依赖配置有误。比如groupId是否正确,或者是否有拼写错误。用户提供的引用[1]中的groupId是jakarta.annotation,artifactId是jakarta.annotation-api,这看起来是正确的。但版本号需要确认。 另外,可能用户的环境问题,比如本地Maven仓库没有正确下载该依赖,或者网络问题导致下载失败。这时候可以建议用户清理本地仓库并重新构建项目,或者检查网络设置。 如果版本确实存在,但与其他依赖存在冲突,可能需要排除冲突的依赖。用户需要检查依赖树,使用mvn dependency:tree命令来查看是否有版本冲突。例如,另一个依赖可能引入了不同版本的jakarta.annotation-api,导致冲突。 另外,用户可能需要升级到更高版本,比如jakarta.annotation-api的2.1.2或更高,如果存在的话。或者,可能用户的项目中使用了其他Jakarta EE组件,需要统一版本号,确保所有Jakarta依赖的版本兼容。 参考引用[2]中的例子,用户之前可能升级了jakarta.servlet-api到6.0.0,所以可能也需要将annotation-api升级到对应的版本。Jakarta的各个组件通常有统一的版本号,比如Jakarta EE 9使用版本2.0.0,Jakarta EE 10使用3.0.0等。如果用户的其他依赖使用较新的版本,而annotation-api的2.1.1可能不兼容,导致错误。 因此,可能的解决方案包括:确认正确的版本号是否存在,更正pom.xml中的版本;检查依赖冲突并排除;升级到兼容的版本;或者检查Maven配置和网络问题。需要一步步引导用户进行排查,确保依赖配置正确,版本兼容,并且能够正确下载。</think>为了解决Jakarta Annotation依赖版本$2.1.1$报错的问题,请按照以下步骤排查和修复: --- ### 一、验证依赖配置正确性 1. **检查版本号是否存在** 访问[Maven中央仓库](https://mvnrepository.com/)查询$jakarta.annotation-api$,发现最新版本为$2.1.1$,但该版本未在仓库中发布[^1]。实际可用版本包括: ```xml <version>2.0.0</version> <!-- Jakarta EE 9 --> <version>2.1.0</version> <!-- 最新稳定版 --> ``` 2. **修正pom.xml配置** 将版本号改为$2.1.0$: ```xml <dependency> <groupId>jakarta.annotation</groupId> <artifactId>jakarta.annotation-api</artifactId> <version>2.1.0</version> </dependency> ``` --- ### 二、排查依赖冲突 1. **查看依赖树** 执行命令检查版本冲突: ```bash mvn dependency:tree -Dincludes=jakarta.annotation ``` 2. **统一Jakarta组件版本** 如果同时使用其他Jakarta依赖(如$jakarta.servlet-api$),需统一版本号: ```xml <properties> <jakarta.version>6.0.0</jakarta.version> </properties> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>${jakarta.version}</version> </dependency> ``` --- ### 三、清理Maven缓存 1. **删除本地仓库残留文件** 定位本地仓库路径(默认在$~/.m2/repository$),删除目录: ```bash rm -rf ~/.m2/repository/jakarta/annotation/ ``` 2. **强制更新依赖** 执行Maven命令重新下载: ```bash mvn clean install -U ``` --- ### 四、兼容性验证 若项目使用Java EE过渡到Jakarta的组件,需确保所有依赖命名空间已从$javax.annotation$迁移到$jakarta.annotation$,例如: ```java import jakarta.annotation.Resource; // 替换 javax.annotation.Resource ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值