Pyspark/SQL:添加像left-semi-join这样的标志列
例如,数据是Pyspark/SQL:添加像left-semi-join这样的标志列,sql,apache-spark,pyspark,Sql,Apache Spark,Pyspark,例如,数据是 customer=spark.createDataFrame([ (0,“票据室”), (1,“Matei Zaharia”), (2,“迈克尔·阿姆布鲁斯特”)])\ .toDF(“客户ID”、“名称”) order=spark.createDataFrame([ (0,0,“产品0”), (1,1,“产品1”), (2,1,“产品2”), (3,3,“产品3”), (4,1,“产品4”)])\ .toDF(“订单ID”、“客户ID”、“产品名称”) 要获得客户订单,我可以使用
customer=spark.createDataFrame([
(0,“票据室”),
(1,“Matei Zaharia”),
(2,“迈克尔·阿姆布鲁斯特”)])\
.toDF(“客户ID”、“名称”)
order=spark.createDataFrame([
(0,0,“产品0”),
(1,1,“产品1”),
(2,1,“产品2”),
(3,3,“产品3”),
(4,1,“产品4”)])\
.toDF(“订单ID”、“客户ID”、“产品名称”)
要获得客户订单,我可以使用left semi
customer.join(订单,['customerid'],“左半”).show()
它可以回来
现在出于比较的原因,我想添加一个标志列,而不是直接过滤掉一些行。所需的输出如下所示:
+----------------+----------------+
|customerid | name |有订单|
+----------+----------------+---------+
|0 |比尔·钱伯斯|正确|
|1 | Matei Zaharia |真的|
|2 |迈克尔·阿姆布鲁斯特|错|
+----------+----------------+---------+
我怎么做?有什么优雅的方法吗?我试着搜索,但没有找到相关的东西,也许我得到了错误的关键字
可以使用SQL的exist/in进行此操作:您可以执行左联接,并根据
orderid
列是否为空来创建has\u order
列。然后使用distinct()
删除重复的行
导入pyspark.sql.f函数
customer.alias(“c”).join(order.alias(“o”),on=[“customerid”],how=“left”)\
.选择(
“c.*”,
f、 col(“o.orderid”).isNull().alias(“has_order”)
)\
.distinct()\
.show()
#+----------+----------------+---------+
#|customerid | name |有订单|
#+----------+----------------+---------+
#|0 |比尔·钱伯斯|正确|
#|1 | Matei Zaharia |正确|
#|2 |迈克尔·阿姆布鲁斯特|错|
#+----------+----------------+---------+
如果要使用类似于正在使用的左半联接的内容,可以合并左半联接和左反联接的结果:
cust\u left\u semi=customer.join(订单,['customerid'],“leftsemi”)\
.withColumn('has_order',f.lit(True))
客户左半成品展示()
#+----------+-------------+---------+
#|customerid | name |有订单|
#+----------+-------------+---------+
#|0 |比尔·钱伯斯|正确|
#|1 | Matei Zaharia |正确|
#+----------+-------------+---------+
cust_left_anti=customer.join(订单,['customerid'],“leftanti”)\
.withColumn('has_order',f.lit(False))
客户左防秀()
#+----------+----------------+---------+
#|customerid | name |有订单|
#+----------+----------------+---------+
#|2 |迈克尔·阿姆布鲁斯特|错|
#+----------+----------------+---------+
cust_left_semi.union(cust_left_anti.show)()
#+----------+----------------+---------+
#|customerid | name |有订单|
#+----------+----------------+---------+
#|0 |比尔·钱伯斯|正确|
#|1 | Matei Zaharia |正确|
#|2 |迈克尔·阿姆布鲁斯特|错|
#+----------+----------------+---------+
您可以使用except
像join\u result.except(customer).withColumn(“has\u order”,lit(False))
然后union
将结果与join\u result.withColumn(“has\u order”,lit(True))
。或者,您可以选择不同的订单id,然后与客户
进行左连接,然后在-时使用,否则
与nvl
进行填充的订单
@Philantrover是的……但与左半部分
的简单性相比,这要复杂得多。@cqcn1991我个人认为join和过滤器是更好的解决方案,但也有leftsemi
和leftanti
联接的union
选项(请参见我的)。好的,我将尝试对这两个解决方案进行基准测试,并给您一些反馈。而且,是否有可能通过简单的解决方案通过SQL实现结果,因为在SQL中支持IN/Exist?如中所示,SparkSQL AFAIK中目前不支持EXISTS/IN。