使用 SQL 更新 Spark 表中的列

Posted

技术标签:

【中文标题】使用 SQL 更新 Spark 表中的列【英文标题】:Update column in Spark table using SQL 【发布时间】:2019-02-28 22:07:09 【问题描述】:

我想在表中添加一列,然后用另一个表中的值填充它。下面是我的问题的高度简化版本。

CREATE TABLE table_1 (
   id INT,
   a DECIMAL(19,2)
)

INSERT INTO TABLE table_1 VALUES (1, 3.0)
INSERT INTO TABLE table_1 VALUES (2, 4.0)

CREATE TABLE table_2 (
   id INT,
   b DECIMAL(19,2),
   c DECIMAL(19,2)
)

INSERT INTO TABLE table_2 VALUES (1, 1.0, 4.0)
INSERT INTO TABLE table_2 VALUES (2, 2.0, 1.0)

-- The next two parts illustrate what I'd like to accomplish
ALTER TABLE table_1 ADD COLUMNS (d Decimal(19,2))

UPDATE table_1
SET d = (table_1.a - table_2.b) / table_2.c
FROM table_2
WHERE table_1.id = table_2.id

最后SELECT * FROM table_1 会产生这样的结果:

+---+----+----+
| id|   a|   d|
+---+----+----+
|  1|3.00|0.50|
|  2|4.00|2.00|
+---+----+----+

但是,当我运行更新命令时,Spark(2.4 版)立即抱怨更新语句。

UPDATE table_1 ...
^^^

最终我需要一个与原始表同名并带有新列的表。仅使用 Spark SQL,我可以做些什么来实现我的目标?似乎我无法执行更新,但有没有我可以做的 SQL hack 来完成相同的最终结果?在我的实际问题中,我需要在一个大表中添加大约 100 列,因此该解决方案也不应该降低性能或制作大量数据副本并占用磁盘空间。

另一种表述我的问题的方式是,我能否使用开源版本的 Spark 完成与 UPDATE 等效的 DataBricks(请参阅 here)?

【问题讨论】:

【参考方案1】:

请记住,Spark 不是数据库;数据框是可以查询的类表引用,但与表不同。您要做的是创建一个视图,将您的表组合成类似表的结构,然后保留或使用该视图。

CREATE TEMPORARY VIEW table_3 AS
SELECT t1.a, t2.b, t2.c, (t1.a - t2.b) / t2.c as d
FROM table_1 t1 INNER JOIN table_2 t2
ON t1.id = t2.id

您最终会希望将该视图写回一个表格,但在添加 100 列中的每一列之后,您不需要执行此操作。

【讨论】:

如果您使用的是常规 Spark,您将能够重新分配和重用您用于数据帧/临时表的名称。直接使用 SparkSQL(通过 JDBC?)我不知道你会怎么做。【参考方案2】:

一种方法是创建 2 个临时表,填充它们,然后将它们连接起来以创建最终表。一般步骤和(未经测试的)代码如下。

1) 创建临时表

CREATE TEMPORARY TABLE temp_table_1 (
   id INT,
   a DECIMAL(19,2)
)

INSERT INTO TABLE temp_table_1 VALUES (1, 3.0)
INSERT INTO TABLE temp_table_1 VALUES (2, 4.0)

CREATE TEMPORARY TABLE temp_table_2 (
   id INT,
   b DECIMAL(19,2),
   c DECIMAL(19,2)
)

INSERT INTO TABLE temp_table_2 VALUES (1, 1.0, 4.0)
INSERT INTO TABLE temp_table_2 VALUES (2, 2.0, 1.0)

2) 创建您的决赛桌

CREATE TABLE table_1 
AS
SELECT t1.id, t1.a, t2.b, (t1.a - t1.b) / t2.c as d
FROM table_1 AS t1
JOIN table_2 AS t2 ON t1.id = t2.id

【讨论】:

以上是关于使用 SQL 更新 Spark 表中的列的主要内容,如果未能解决你的问题,请参考以下文章

SQL UPDATE - 如何使用另一个表更新一个表中的列?

SQL 脚本。更新表中的列

PL/SQL 使用一张表中的列数据更新表,基于不同表之间的相等性

当没有明确的列可以加入时,如何使用另一个表中的值更新 sql 表?

获取 ajax 请求以更新 SQL 表中的列

当 SQL Server 表中的列“createdDate”从现在起经过 90 天后,如何更新其具有数百万行的列?我们可以使用触发器吗?