sql - 派斯帕克/SQL : add a flag column like left semi join

标签 sql apache-spark pyspark

比如数据是

customer = spark.createDataFrame([
    (0, "Bill Chambers"),
    (1, "Matei Zaharia"),
    (2, "Michael Armbrust")])\
  .toDF("customerid", "name")

order = spark.createDataFrame([
    (0, 0, "Product 0"),
    (1, 1, "Product 1"),
    (2, 1, "Product 2"),
    (3, 3, "Product 3"),
    (4, 1, "Product 4")])\
  .toDF("orderid", "customerid", "product_name")

为了让客户下订单,我可以用 left semi

customer.join(order, ['customerid'], "left_semi").show()

可以返回

enter image description here

现在为了比较,我想添加一个标志列,而不是直接过滤掉一些行。所需的输出如下所示:

+----------+----------------+---------+ 
|customerid|            name|has_order| 
+----------+----------------+---------+ 
|         0| Bill Chambers  |     true| 
|         1| Matei Zaharia  |     true| 
|         2|Michael Armbrust|    false| 
+----------+----------------+---------+

我该怎么做?有什么优雅的方法吗?我尝试搜索但没有找到相关内容,可能是我输入的关键字有误?


可以用 SQL 的 exist/in 来完成吗?:Spark replacement for EXISTS and IN

最佳答案

您可以进行左连接,并使用 pyspark.sql.Column.isNull()根据 orderid 列是否不为空来创建 has_order 列。然后使用 distinct() 删除重复的行。

import pyspark.sql.functions as f
customer.alias("c").join(order.alias("o"), on=["customerid"], how="left")\
    .select(
        "c.*",
        f.col("o.orderid").isNull().alias("has_order")
    )\
    .distinct()\
    .show()
#+----------+----------------+---------+
#|customerid|            name|has_order|
#+----------+----------------+---------+
#|         0|   Bill Chambers|     true|
#|         1|   Matei Zaharia|     true|
#|         2|Michael Armbrust|    false|
#+----------+----------------+---------+

如果您想使用类似于您正在使用的左半连接的东西,您可以合并左半连接和左反连接的结果:

cust_left_semi = customer.join(order, ['customerid'], "leftsemi")\
    .withColumn('has_order', f.lit(True))
cust_left_semi.show()
#+----------+-------------+---------+
#|customerid|         name|has_order|
#+----------+-------------+---------+
#|         0|Bill Chambers|     true|
#|         1|Matei Zaharia|     true|
#+----------+-------------+---------+

cust_left_anti = customer.join(order, ['customerid'], "leftanti")\
    .withColumn('has_order', f.lit(False))
cust_left_anti.show()
#+----------+----------------+---------+
#|customerid|            name|has_order|
#+----------+----------------+---------+
#|         2|Michael Armbrust|    false|
#+----------+----------------+---------+

cust_left_semi.union(cust_left_anti).show()
#+----------+----------------+---------+
#|customerid|            name|has_order|
#+----------+----------------+---------+
#|         0|   Bill Chambers|     true|
#|         1|   Matei Zaharia|     true|
#|         2|Michael Armbrust|    false|
#+----------+----------------+---------+

关于sql - 派斯帕克/SQL : add a flag column like left semi join,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50510293/

相关文章:

mysql - 根据以前的销售预测库存消耗率

php - 从sql中获取实际的年月数据

scala - Spark 错误 - 退出状态 : 143. 诊断:根据请求终止容器

python - 为什么我的简单Spark应用程序运行这么慢?

Pyspark 使用子字符串更改列

sql - pyspark sql 查询 : count distinct values with conditions

mysql - knex JS mysql 中出现错误 "res.json is not a function"

sql - 撤消日志错误 : No more space left over in system tablespace for allocating UNDO log pages

apache-spark - 如何在执行之前更改查询计划(可能关闭优化)?

apache-spark - 在 pyspark 数据框中平面映射一个 collect_set