Spark SQL :来自另一个 SELECT 语句的列(二叉搜索树)

Spark SQL : Column from Another SELECT Statement (Binary Search Tree)

我正在尝试使用 SparkSQL 构建 BST,这可以使用主 SELECT 语句中的另一个 SELECT 语句轻松完成,但 SparkSQL 不会支持 SELECT 内的 SELECT 作为列。

BST 的图形表示如下:

输入是 BST.Goal 的行列表示是使用输入 table 数据生成输出 table。

这可以通过 select 中的 select 轻松实现,下面 SQL 应该这样做:

SELECT t.node,
    CASE
        WHEN t.parent IS NULL THEN 'root'
        WHEN EXISTS (SELECT t1.parent FROM bst t1 WHERE t1.parent = t.node) THEN 'inner'        
        ELSE 'leaf'
    END
FROM bst t

由于 SparkSQL 没有上述功能,我不得不通过变通来做到这一点。

spark.sql("""SELECT node, 'inner' AS desc
FROM bst t
WHERE EXISTS (SELECT 1
                        FROM bst t1
                        WHERE t1.parent=t.node)
            AND parent IS NOT NULL

UNION ALL

SELECT node,'leaf' AS desc
FROM bst t
WHERE NOT EXISTS (SELECT 1
                        FROM bst t1
                        WHERE t1.parent=t.node)
            AND parent IS NOT NULL          

UNION ALL

SELECT node,'root' AS desc
FROM bst t
WHERE parent IS NULL""").show()

快速创建虚拟数据的命令

data = \
  [(1, 2),
  (3, 2),
  (6, 8),
  (9, 8),
  (2, 5),
  (8, 5),
  (5, None)]
df = spark.createDataFrame(data, ["node", "parent"])
df.createOrReplaceTempView ("bst")

我正在使用 Spark 2.1 版,还有其他更好的优化方法吗?

您需要进行自连接,但您可以在一条语句中完成(相对于使用联合的两条语句)。

尝试一下:

select distinct 
  case 
    when n.parent is null then 'root' 
    when child.node is null then 'leaf'
    else 'inner' end
  ,n.node 
from bst n 
left outer join bst child
on n.node = child.parent
;

这是使用 SparkSQL 的一种方式

df.withColumn("TYPE",functions \
.when(functions.col("parent").isNull(),"root") \
.when(functions.col("node")\
.isin(list(df.select(functions.col("parent")).distinct().rdd.map(lambda x:x[0]).collect())),"inner") \
.otherwise("leaf"))\
.drop("parent")\
.show()

+----+-----+
|node| TYPE|
+----+-----+
|   1| leaf|
|   3| leaf|
|   6| leaf|
|   9| leaf|
|   2|inner|
|   8|inner|
|   5| root|
+----+-----+

如果可能的话,你能帮我优化一下吗