oracle和hive的行列转换,SQL行转列、列转行

本文介绍了在Oracle和Hive中如何进行行转列和列转行的操作。通过Oracle的pivot、聚合函数和unpivot函数,以及Hive的聚合函数和explode/posexplode函数,展示了在不同场景下实现数据转换的方法。

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

oracle和hive如何实现行转列、列转行?

现在有oracle表student:三个字段name、subject、score,里面的数据是:
张三 语文 60
张三 数学 70
张三 英语 55
李四 语文 90
李四 英语 75
李四 物理 30
王五 语文 40
王五 英语 80
王五 物理 65

1. 用oracle SQL实现下面的统计结果?
name 语文 数学 英语 物理
张三 60 70 55 0
李四 90 0 75 30
王五 40 0 80 65

  • 方案1
    可以用oracle的pivot旋转函数处理:
select * from student pivot( sum(score) for subject in ("语文","数学","英语","物理"));
  • 方案2
    用聚合函数处理:
select
name,
--等同于max(case when subject="语文" then score else 0 end) as 语文,
max(if(subject="语文",score,0)) as 语文,
max(if(subject="数学",score,0)) as 数学,
max(if(subject="英语",score,0)) as 英语,
max(if(subject="物理",score,0)) as 物理
from student
group by name;
  • 方案3
    用union来连接:
(select 
--等同于"张三",if("语文",score,0) as 语文,
"张三",case subject when "语文" then score else 0 
<think>好的,用户想了解SQL行转列的实现方法示例。首先,我需要回忆一下行转列的常见方法。根据引用[1],像OracleSQL Server这些数据库支持UNPIVOT函数,可以直接使用。不过用户可能需要通用的方法,或者不同数据库的解决方案。 然后,引用[2]提到当数不固定时,处理起来比较麻烦。这时候可能需要动态SQL,但动态SQL在不同数据库中的写法不同,比如MySQLSQL Server。不过动态SQL比较复杂,可能用户需要先了解基础方法。 接下来,引用[3]中的例子用了LATERAL VIEWexplode函数,这应该是Hive或者Spark SQL中的用法,适用于处理数组或者分隔符分割的字段。这部分可能需要单独说明,特别是处理多值字段的情况。 引用[4]展示了使用UNPIVOTPIVOT的组合来实现行列转换,这在SQL Server中适用。不过用户可能想知道更通用的方法,比如使用CASE WHEN聚合函数,这在没有PIVOT支持的数据库(如MySQL)中是常用的。 所以,我应该分几种情况来回答:使用数据库自带函数(如PIVOT/UNPIVOT)、使用通用SQL方法(CASE WHEN + 聚合)、动态处理,以及特定场景如Hive中的处理。同时,给出示例代码,并标注对应的引用来源,确保用户知道每个方法的出处。 还要注意用户可能对动态处理感兴趣,因为引用[2]提到不固定的情况,这部分可能需要额外说明动态SQL的实现,但也要指出其复杂性。另外,确保示例清晰,比如静态行转列的示例,以及如何处理多值拆分。 最后,生成相关问题时要涵盖不同数据库的实现、动态处理、性能优化应用场景,这样用户可以有进一步的学习方向。</think>### SQL行转列实现方法及示例 行转列(Pivot)是数据转换中常见的需求,主要用于将行数据转换为多展示。以下是不同场景下的实现方法及示例: --- #### 一、固定行转列 **适用场景**:已知转换后的名且数固定 **实现方法**:使用`CASE WHEN`结合聚合函数 **示例**:将学生各科成绩从行转为 ```sql SELECT 姓名, MAX(CASE WHEN 科目 = '语文' THEN 成绩 ELSE 0 END) AS 语文, MAX(CASE WHEN 科目 = '数学' THEN 成绩 ELSE 0 END) AS 数学, MAX(CASE WHEN 科目 = '英语' THEN 成绩 ELSE 0 END) AS 英语 FROM 成绩表 GROUP BY 姓名; ``` --- #### 二、数据库内置函数(支持PIVOT的数据库) 1. **SQL Server/Oracle** 使用`PIVOT`函数直接转换: ```sql SELECT * FROM ( SELECT 姓名, 科目, 成绩 FROM 成绩表 ) AS src PIVOT ( MAX(成绩) FOR 科目 IN ([语文], [数学], [英语]) ) AS pvt; ``` [^4] 2. **Hive/Spark SQL** 使用`LATERAL VIEW`处理多值字段: ```sql SELECT id, industry_split FROM 原始表 LATERAL VIEW EXPLODE(SPLIT(industry, ',')) tmp AS industry_split; ``` [^3] --- #### 、动态处理(名不固定) **适用场景**:转换后的名未知或动态变化 **实现方法**:动态生成SQL语句 **示例**(MySQL动态SQL): ```sql SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT CONCAT('MAX(CASE WHEN 科目 = ''', 科目, ''' THEN 成绩 ELSE 0 END) AS `', 科目, '`') ) INTO @sql FROM 成绩表; SET @sql = CONCAT('SELECT 姓名, ', @sql, ' FROM 成绩表 GROUP BY 姓名'); PREPARE stmt FROM @sql; EXECUTE stmt; ``` [^2] --- #### 四、反向操作(转行) 使用`UNPIVOT`或`UNION ALL`实现转行: ```sql -- SQL Server示例 SELECT 姓名, 科目, 成绩 FROM 成绩表 UNPIVOT (成绩 FOR 科目 IN ([语文], [数学], [英语])) AS unpvt; ``` [^1] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值