SQL 查询横表变竖表

/*
普通行列转换


假设有张学生成绩表(tb)如下:
Name Subject Result
张三 语文  74
张三 数学  83
张三 物理  93
李四 语文  74
李四 数学  84
李四 物理  94
*/

-------------------------------------------------------------------------
/*

想变成
姓名         语文        数学        物理         
---------- ----------- ----------- -----------
李四         74          84          94
张三         74          83          93
*/

createtable tb
(
   Name   
varchar(10) ,
   Subject
varchar(10) ,
   Result 
int
)

insertinto tb(Name , Subject , Result) values('张三' , '语文' , 74)
insertinto tb(Name , Subject , Result) values('张三' , '数学' , 83)
insertinto tb(Name , Subject , Result) values('张三' , '物理' , 93)
insertinto tb(Name , Subject , Result) values('李四' , '语文' , 74)
insertinto tb(Name , Subject , Result) values('李四' , '数学' , 84)
insertinto tb(Name , Subject , Result) values('李四' , '物理' , 94)
go

--静态SQL,指subject只有语文、数学、物理这三门课程。
select name 姓名,
 
max(case subject when'语文'then result else0end) 语文,
 
max(case subject when'数学'then result else0end) 数学,
 
max(case subject when'物理'then result else0end) 物理
from tb
groupby name
/*
姓名         语文        数学        物理         
---------- ----------- ----------- -----------
李四         74          84          94
张三         74          83          93
*/

--动态SQL,指subject不止语文、数学、物理这三门课程。
declare@sqlvarchar(8000)
set@sql='select Name as '+'姓名'
select@sql=@sql+' , max(case Subject when '''+ Subject +''' then Result else 0 end) ['+ Subject +']'
from (selectdistinct Subject from tb) as a
set@sql=@sql+' from tb group by name'
exec(@sql)
/*
姓名         数学        物理        语文         
---------- ----------- ----------- -----------
李四         84          94          74
张三         83          93          74
*/

-------------------------------------------------------------------
/*
加个平均分,总分
姓名         语文        数学        物理        平均分                总分         
---------- ----------- ----------- ----------- -------------------- -----------
李四         74          84          94          84.00                252
张三         74          83          93          83.33                250
*/

--静态SQL,指subject只有语文、数学、物理这三门课程。
select name 姓名,
 
max(case subject when'语文'then result else0end) 语文,
 
max(case subject when'数学'then result else0end) 数学,
 
max(case subject when'物理'then result else0end) 物理,
 
cast(avg(result*1.0) asdecimal(18,2)) 平均分,
 
sum(result) 总分
from tb
groupby name
/*
姓名         语文        数学        物理        平均分                总分         
---------- ----------- ----------- ----------- -------------------- -----------
李四         74          84          94          84.00                252
张三         74          83          93          83.33                250
*/

--动态SQL,指subject不止语文、数学、物理这三门课程。
declare@sql1varchar(8000)
set@sql1='select Name as '+'姓名'
select@sql1=@sql1+' , max(case Subject when '''+ Subject +''' then Result else 0 end) ['+ Subject +']'
from (selectdistinct Subject from tb) as a
set@sql1=@sql1+' , cast(avg(result*1.0) as decimal(18,2)) 平均分,sum(result) 总分 from tb group by name'
exec(@sql1)
/*
姓名         数学        物理        语文        平均分                总分         
---------- ----------- ----------- ----------- -------------------- -----------
李四         84          94          74          84.00                252
张三         83          93          74          83.33                250
*/

droptable tb   

---------------------------------------------------------
--
-------------------------------------------------------
/*

如果上述两表互相换一下:即

姓名 语文 数学 物理
张三 74  83  93
李四 74  84  94

想变成
Name       Subject Result     
---------- ------- -----------
李四         语文      74
李四         数学      84
李四         物理      94
张三         语文      74
张三         数学      83
张三         物理      93
*/

createtable tb1
(
   姓名
varchar(10) ,
   语文
int ,
   数学
int ,
   物理
int
)

insertinto tb1(姓名 , 语文 , 数学 , 物理) values('张三',74,83,93)
insertinto tb1(姓名 , 语文 , 数学 , 物理) values('李四',74,84,94)

select*from
(
 
select 姓名 as Name , Subject ='语文' , Result = 语文 from tb1
 
unionall
 
select 姓名 as Name , Subject ='数学' , Result = 数学 from tb1
 
unionall
 
select 姓名 as Name , Subject ='物理' , Result = 物理 from tb1
) t
orderby name , case Subject when'语文'then1when'数学'then2when'物理'then3when'总分'then4end

--------------------------------------------------------------------
/*
加个平均分,总分
Name       Subject     Result              
---------- -------    --------------------
李四         语文      74.00
李四         数学      84.00
李四         物理      94.00
李四         平均分    84.00
李四         总分      252.00
张三         语文      74.00
张三         数学      83.00
张三         物理      93.00
张三         平均分    83.33
张三         总分      250.00
*/

select*from
(
 
select 姓名 as Name , Subject ='语文' , Result = 语文 from tb1
 
unionall
 
select 姓名 as Name , Subject ='数学' , Result = 数学 from tb1
 
unionall
 
select 姓名 as Name , Subject ='物理' , Result = 物理 from tb1
 
unionall
 
select 姓名 as Name , Subject ='平均分' , Result =cast((语文 + 数学 + 物理)*1.0/3asdecimal(18,2)) from tb1
 
unionall
 
select 姓名 as Name , Subject ='总分' , Result = 语文 + 数学 + 物理 from tb1
) t
orderby name , case Subject when'语文'then1when'数学'then2when'物理'then3when'平均分'then4when'总分'then5end

droptable tb1

<think>嗯,用户想知道如何将SUM函数生成的格转换为横向格,使用SQL或Excel。首先,我需要回忆一下Excel和SQL中处理数据转置的方法。 在Excel里,我记得转置功能可以通过复制粘贴时的转置选项来实现。不过用户提到使用SUM函数生成的结果,可能是一个动态的汇总,这样的话直接转置可能不会随着数据更新而化。所以可能需要用公式或者数据透视来动态转置。 比如,使用TRANSPOSE函数。TRANSPOSE是数组公式,需要按Ctrl+Shift+Enter,或者在新版本的Excel中动态数组功能可能自动扩展。另外,数据透视也可以调整行和列的字段,把行标签拖到列标签,这样就能实现横向显示。不过数据透视的设置可能需要调整,比如将原来的行字段改为列字段,这样汇总结果就会横向展示。 然后是SQL部分。用户可能有一个,比如每个类别有一行汇总值,想转成每个类别作为列。这通常叫做行转列,在SQL中可以用CASE语句配合聚合函数,或者使用PIVOT关键字。比如,使用SUM配合CASE WHEN来为每个类别生成单独的列,或者直接使用PIVOT语法,这样查询结果就会是横向的。 需要注意的是,不同的数据库对PIVOT的支持不同,比如SQL Server有PIVOT,而MySQL可能需要用CASE语句来实现。所以可能需要根据具体的数据库类型来调整语法。 另外,用户可能还希望保持动态更新,比如当原始数据化时,转置后的结果也能自动更新。在Excel中,使用公式或者数据透视的话,刷新后结果会更新。而在SQL中,视图或者存储过程可以保持动态,但具体实现要看数据库的结构和权限。 还需要考虑性能问题,特别是在处理大数据量时,SQL的行转列可能会影响查询速度,需要适当的索引或者优化。Excel中如果数据量很大,使用数组公式可能会让文件慢,这时候数据透视可能更高效。 可能用户的需求是生成报或者展示数据,横向格更易于阅读。需要确保转置后的格式符合需求,比如列名正确,数据类型合适,没有数据丢失或错误。 总结一下,Excel的方法包括复制粘贴转置、TRANSPOSE函数、数据透视SQL的方法包括CASE语句和PIVOT操作。需要根据具体情况选择合适的方法,并注意动态更新和性能问题。</think>### 使用SQL或Excel将SUM函数结果从转为横表的方法 #### 一、Excel实现方法 1. **基础转置功能** 若SUM生成的格是静态结果,可直接通过复制粘贴实现转置: - 选中格区域 → 复制 → 右键粘贴 → 选择「转置」选项。 - *缺点*:无法动态更新[^2]。 2. **使用TRANSPOSE函数** 若需动态关联原始数据,可用数组公式: ```excel =TRANSPOSE(SUM函数生成的向区域) ``` - 需按`Ctrl+Shift+Enter`组合键输入数组公式(Excel 365支持自动扩展)[^3]。 3. **数据透视转置** 通过调整行列字段实现动态横向展示: - 创建数据透视 → 将原行字段拖入「列」区域,数值字段拖入「值」区域 → 右键「值」字段选择`值字段设置`为求和。 #### 二、SQL实现方法 1. **CASE语句行转列** 适用于所有SQL数据库: ```sql SELECT SUM(CASE WHEN 分类字段='A' THEN 数值字段 ELSE 0 END) AS A类总和, SUM(CASE WHEN 分类字段='B' THEN 数值字段 ELSE 0 END) AS B类总和 FROM 名; ``` 2. **PIVOT语法(SQL Server/Oracle)** 专用语法更简洁: ```sql SELECT * FROM ( SELECT 分类字段, 数值字段 FROM 名 ) AS 源 PIVOT ( SUM(数值字段) FOR 分类字段 IN ([A], [B]) ) AS 横向; ``` #### 三、性能与动态性对比 | 方法 | 动态更新 | 适用场景 | 复杂度 | |--------------------|----------|---------------------|--------| | Excel复制转置 | ❌ | 静态结果快速转换 | 低 | | TRANSPOSE函数 | ✅ | 小规模动态数据 | 中 | | 数据透视 | ✅ | 中大规模结构化数据 | 中 | | SQL CASE语句 | ✅ | 数据库端灵活处理 | 高 | | SQL PIVOT | ✅ | 支持PIVOT的数据库 | 中 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值