我正在尝试使用SparkSQL构建BST,这可以使用主SELECT语句中的另一个SELECT语句轻松完成,但SparkSQL不支持SELECT中的SELECT作为列。
BST的图形表示如下:
输入是BST的行列表示.Goal是使用输入表数据生成输出表。
root:没有父节点
内部:拥有父节点以及子节点
这可以通过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版,还有其他更优化的方法吗?
答案 0 :(得分: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
;
答案 1 :(得分:0)
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|
+----+-----+
如果可能的话,你能帮我优化一下吗