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。
root : 没有父节点
inner : 既有父节点又有子节点
- 叶子:只有父节点,没有子节点
这可以通过 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|
+----+-----+
如果可能的话,你能帮我优化一下吗
我正在尝试使用 SparkSQL 构建 BST,这可以使用主 SELECT 语句中的另一个 SELECT 语句轻松完成,但 SparkSQL 不会支持 SELECT 内的 SELECT 作为列。
BST 的图形表示如下:
输入是 BST.Goal 的行列表示是使用输入 table 数据生成输出 table。
root : 没有父节点
inner : 既有父节点又有子节点
- 叶子:只有父节点,没有子节点
这可以通过 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|
+----+-----+
如果可能的话,你能帮我优化一下吗