复杂高级type的join操作
1、只要能返回布尔型结果(True/False)的判断表达式,都可以作为JOIN的关联表达式
2、关联操作后的结果表中处理重复列名的三种方法
3、spark做JOIN时两个表/DF的通讯机制,三种情况
一、只要能返回布尔型结果(True/False)的判断表达式expr,都可以作为JOIN的关联表达式
1、array_contains()函数,两个DF没有两列能使用明确的相等=条件来判断,但是能发现两列有包含的关系
//in scala, 使用array_contains表达式来做两个DF的JOIN操作
import org.apache.spark.sql.functions.expr
df1.withColumnRenamed("id", "personId")\
.join(df2, expr("array_contains(spark_status, id)")).show()
# in Python
from pyspark.sql.functions import expr
df1.withColumnRenamed("id", "personId")\
.join(df2, expr("array_contains(spark_status, id)")).show()
-- in SQL
SELECT * FROM
(select id as personId, name, graduate_program, spark_status FROM table1)
INNER JOIN table2 ON array_contains(spark_status, id)
引申:两个表可以使用array_contains函数在实践中的应用是怎样的呢?
比如可以用来做列过滤,再加上与之前的left_semi 一起使用,不仅可以提高关联的执行效率,还不能写UDF来过滤,岂不是很方便。
2、注意不是随便使用函数表达式就可以的,比如使用用来判断>= 或 <=的表达式 就会报失败
3、如果是自定义的UDF表达式呢?能不能成功关联呢?
二、关联操作后的结果表中处理重复列名的三种方法
1、什么情况下会产生重复的列名?
(1)两个DataFrame做JOIN操作的时候,使用的是布尔型表达式,但并没有指定要哪个表的该列
比如,select * from df1 join df2 on df1.col1=df2.col2 ,这时候会把df1 和df2的col1列都选上,就有了重复列。而一般我们会指定 select df1.col1,df2.col2,...这样避免重复的列名。
(2)两个DataFrame做JOIN操作的时候,有些列也具有相同的列名,但你并没有使用它们做关联
比如,表1和表2都具有列名col1,col2,col3。但你做关联的时候,只使用了 df1.col1=df2.col1,那么结果表中就包含了表1的col2、col3 和表2的col2、col3,他们就具有了重复的列名。
#in python
#使用列表list[](python语言)(scala语言中是seq()序列)这样的方式做JOIN,能避免col1的重复问题,但因为两个DF还含有col2,col3重复的列名,所以还是会有重复
df1.join(df2,["col1"])
#当然,如果关联条件是col1,col2,col3都关联,就不会有列名重复问题了。
df1.join(df2,["col1","col2","col3"])
2、处理重复列名的三种方法
(1)方法一:将JOIN的布尔型表达式换成string或list列表-python语言(sequence序列-scala语言)
#in python
#1、使用string形式做JOIN,如果相同的列名只有关联列col1的时候
df1.join(df2,"col1").select("col1")
#2、使用列表list做JOIN,如果相同的列名有多个,并且都要做关联时
df1.join(df2,["col1","col2","col3"])
三、spark做JOIN时两个表/DF的通讯机制(大表 和 大表, 大表 和 小表, 小表 和 小表)
1、大表 和 大表,
2、大表 和 小表,
3、小表 和 小表