PostgreSQL | 数据库语法-两表关联更新语法

在尝试使用MySQL的语法更新PostgreSQL中的cq_compliance_question表的serial_number字段时遇到错误。经过多次尝试和修改,发现PostgreSQL要求在SET关键字后的列名直接使用,而不能包含表名或别名。最终的正确更新语句为:UPDATE cq_compliance_question AS c1, cq_compliance_question_temp AS c2 SET c1.serial_number = c2.serial_number WHERE c1.id = c2.id。这表明PostgreSQL与MySQL在两表关联更新的语法上存在差异。" 111498614,10295621,Java POI 实现Excel联动下拉框,"['Java', 'Excel处理', 'POI库', '数据验证', '前端框架']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PostgreSQL 两表关联更新

问题:我需要对目标表cq_compliance_question的serial_number字段的值进行维护,由于cq_compliance_question数据量太大,所以我创建了临时表cq_compliance_question_temp来辅助操作。所以,我需要通过这两张表关联来完成对目标表字段serial_number值的维护。

我采用MySQL的写法:

UPDATE cq_compliance_question cq,
 cq_compliance_question_temp cqt
SET cq.serial_number = cqt.serial_number_2
WHERE
	cq."id" = cqt."id"

但是此时Navicat是报错的,错误信息:

[SQL]UPDATE cq_compliance_question cq,
 cq_compliance_question_temp cqt
SET cq.serial_number = cqt.serial_number_2
WHERE
	cq."id" = cqt."id"

[Err] ERROR:  syntax error at or near ","
LINE 1: UPDATE cq_compliance_question cq,
                                        ^

说我语法错误,但这种写法在MySQL是ok的。

所以我开始对该写法进行修改。
第一次修改:

UPDATE cq_compliance_question cq
SET cq.serial_number = cqt.serial_numb
<think>好的,我需要解决用户的问题,即如何通过SQL使用CASE WHEN将包含id、Var1、Var2、Var3、Var4的宽转换为长,输出id、Var_name和Value的结构。用户之前提到了使用CASE WHEN进行行列转换,特别是行转列,但现在需要的是宽转长,即列转行,这可能与之前的思路相反。 首先,我需要明确用户的需求。宽结构中的每个id对应多个列(Var1到Var4),而用户希望每个id对应多行,每行包含一个Var_name(如Var1、Var2等)和对应的Value。这种情况下,常规的方法是使用UNION ALL或者SQL的UNPIVOT操作。不过用户特别提到要使用CASE WHEN,这可能意味着用户希望用这种方法实现转换,或者对UNPIVOT不太熟悉。 回顾用户提供的引用内容,引用[4]中提到了使用MAX(CASE WHEN ...)进行宽转长,但那是行转列的例子,而用户现在需要的是列转行。引用[1]中的pivot_longer函数在R中用于长转换,但用户现在用的是SQL。引用[4]中的SQL示例是宽转长,但使用的是CASE WHEN的行转列,所以可能需要逆向思考。 接下来,我需要考虑如何用SQL的CASE WHEN来实现列转行。通常,UNPIVOT是更直接的方法,但有些数据库不支持,或者用户希望用更基础的方法。这时候,可以通过为每个变量创建多行,然后使用UNION ALL来合并结果。例如,对每个Var列,生成一行id、Var_name和Value,然后将这些结果合并。 不过用户特别提到使用CASE WHEN,可能的思路是将每个Var列的值提取出来,并通过CASE WHEN来生成Var_name。例如,对于每个变量,生成对应的行,使用CASE WHEN判断当前行对应的变量名,并提取相应的值。这可能需要结合CROSS JOIN或者生成序列来实现变量的展开。 例如,可以创建一个包含所有变量名的临时(如Var1, Var2, Var3, Var4),然后与原始进行CROSS JOIN,生成每个id对应的每个变量名,然后用CASE WHEN根据变量名选择对应的值。这种方法实际上模拟了UNPIVOT的操作。 具体步骤可能如下: 1. 为每个变量名创建一个虚拟,或使用VALUES子句生成变量名列2. 将原始与变量名进行CROSS JOIN,生成每个id与每个变量名的组合。 3. 使用CASE WHEN根据变量名选择对应的列值作为Value。 4. 最后筛选出Value不为空的行(如果需要)。 例如,在SQL中,可以这样写: SELECT id, 'Var1' AS Var_name, Var1 AS Value FROM UNION ALL SELECT id, 'Var2' AS Var_name, Var2 AS Value FROM UNION ALL SELECT id, 'Var3' AS Var_name, Var3 AS Value FROM UNION ALL SELECT id, 'Var4' AS Var_name, Var4 AS Value FROM ; 这种方法虽然可行,但当变量较多时,代码会变得冗长。但用户可能希望使用CASE WHEN而不是多个UNION,这时候可能需要结合生成的行号或变量列来动态展开。 另外,考虑到用户之前的问题是关于行转列使用CASE WHEN,现在列转行可能需要不同的方法。需要确认用户是否确实希望用CASE WHEN,或者是否接受其他方法如UNION ALL。 不过根据用户的问题,明确要求使用CASE WHEN进行转换,因此可能需要另一种方式。例如,使用CROSS JOIN生成每个变量名的行,然后通过CASE WHEN来提取对应的值。例如: SELECT id, var_name, CASE var_name WHEN 'Var1' THEN Var1 WHEN 'Var2' THEN Var2 WHEN 'Var3' THEN Var3 WHEN 'Var4' THEN Var4 END AS Value FROM 原始 CROSS JOIN (VALUES ('Var1'), ('Var2'), ('Var3'), ('Var4')) AS vars(var_name); 这种方法在支持VALUES子句的数据库中是可行的,比如SQL Server或PostgreSQL。但如果是MySQL,可能需要使用UNION ALL来生成变量名列。 总结,用户需要将宽转换为长,使用CASE WHEN。可能的解决方案是结合CROSS JOIN生成变量名列,然后使用CASE WHEN提取对应的列值。需要根据具体的数据库语法进行调整,但核心思路是通过生成变量名的行,然后为每个变量名选择对应的值。</think>### Spark SQL使用CASE WHEN实现宽转长方案 #### 一、核心实现思路 通过`CROSS JOIN`生成变量名集合,配合`CASE WHEN`提取对应列值,最终生成三列结构: $$(id,\ Var\_name,\ Value)$$ #### 二、完整SQL实现 ```sql -- 创建示例宽(含id, Var1-Var4) CREATE OR REPLACE TEMP VIEW wide_table AS SELECT * FROM VALUES (1, 10, 20, 30, 40), (2, 50, 60, 70, 80) AS tab(id, Var1, Var2, Var3, Var4); -- 使用CASE WHEN实现宽转长 SELECT id, var_name, CASE var_name WHEN 'Var1' THEN Var1 WHEN 'Var2' THEN Var2 WHEN 'Var3' THEN Var3 WHEN 'Var4' THEN Var4 END AS value FROM wide_table CROSS JOIN ( SELECT explode(array('Var1','Var2','Var3','Var4')) AS var_name ) AS var_list; ``` #### 三、关键步骤解析 1. **生成变量名列**: - 使用`array()`创建变量名集合 - `explode()`函数展开为多行[^1] ```sql SELECT explode(array('Var1','Var2','Var3','Var4')) AS var_name ``` 2. **关联原始**: - `CROSS JOIN`产生笛卡尔积,为每个id生成4条记录(对应4个变量) 3. **动态值提取**: - `CASE WHEN`根据var_name定位对应列值 - 自动处理数据类型一致性(需确保所有Var列类型相同) #### 四、执行结果示例 ``` +---+--------+-----+ |id |var_name|value| +---+--------+-----+ |1 |Var1 |10 | |1 |Var2 |20 | |1 |Var3 |30 | |1 |Var4 |40 | |2 |Var1 |50 | |2 |Var2 |60 | |2 |Var3 |70 | |2 |Var4 |80 | +---+--------+-----+ ``` #### 五、性能优化建议 1. **列过滤**: ```sql CROSS JOIN (SELECT var_name FROM var_list WHERE var_name IN ('Var1','Var3')) ``` 减少不必要的列转换 2. **分区控制**: ```sql SET spark.sql.shuffle.partitions=8; ``` 根据集群规模调整shuffle并行度 3. **类型转换**: ```sql CASE var_name WHEN 'Var1' THEN CAST(Var1 AS STRING) ... ``` 统一输出值的数据类型 #### 六、对比UNPIVOT语法 | 特性 | CASE WHEN方案 | UNPIVOT语法 | |--------------------|-----------------------------|-------------------------| | 代码可读性 | 需要显式列出所有列 | 声明式语法更简洁 | | 动态扩展 |修改SQL列列 | 同样需要列列 | | 空值处理 | 自动保留原始空值 | 自动过滤NULL需额外处理 | | 版本兼容 | 支持所有Spark版本 | 需Spark 3.0+ | | 执行计划 | 产生Project+Expand组合 | 直接生成Expand算子 |
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值