Sql 行转列问题总结
行转列问题总结
1、行转列
---1、最简单的行转列
/*
问题:假设有张学生成绩表(tb)如下:
姓名 课程 分数
张三 语文 74
张三 数学 83
张三 物理 93
李四 语文 74
李四 数学 84
李四 物理 94
想变成(得到如下结果):
姓名 语文 数学 物理
李四 74 84 94
张三 74 83 93
*/
--测试用
IF OBJECT_ID('[tb]') IS NOT NULL DROP TABLE [tb]
GO
create table tb(姓名 varchar(10) , 课程 varchar(10) , 分数 int)
insert into tb values('张三' , '语文' , 74)
insert into tb values('张三' , '数学' , 83)
insert into tb values('张三' , '物理' , 93)
insert into tb values('李四' , '语文' , 74)
insert into tb values('李四' , '数学' , 84)
insert into tb values('李四' , '物理' , 94)
go
--SQL SERVER 2000 动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
declare @sql varchar(8000)
set @sql = 'select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [' + 课程 + ']'
from (select distinct 课程 from tb) as a
set @sql = @sql + ' from tb group by 姓名'
exec(@sql)
--通过动态构建@sql,得到如下脚本
select 姓名 as 姓名 ,
max(case 课程 when '语文' then 分数 else 0 end) 语文,
max(case 课程 when '数学' then 分数 else 0 end) 数学,
max(case 课程 when '物理' then 分数 else 0 end) 物理
from tb
group by 姓名
--SQL SERVER 2005 动态SQL。
declare @sql varchar(8000)
select @sql = isnull(@sql + '],[' , '') + 课程 from tb group by 课程
set @sql = '[' + @sql + ']'
exec ('select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b')
--得到SQL SERVER 2005 静态SQL。
select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b
--查询结果
/*
姓名 数学 物理 语文
---------- ----------- ----------- -----------
李四 84 94 74
张三 83 93 74
(所影响的行数为 2 行)
*/
--2 加合计
/*
问题:在上述结果的基础上加平均分,总分,得到如下结果:
姓名 语文 数学 物理 平均分 总分
---- ---- ---- ---- ------ ----
李四 74 84 94 84.00 252
张三 74 83 93 83.33 250
*/
--SQL SERVER 2000 静态SQL。
select 姓名 姓名,
max(case 课程 when '语文' then 分数 else 0 end) 语文,
max(case 课程 when '数学' then 分数 else 0 end) 数学,
max(case 课程 when '物理' then 分数 else 0 end) 物理,
cast(avg(分数*1.0) as decimal(18,2)) 平均分,
sum(分数) 总分
from tb
group by 姓名
--SQL SERVER 2000 动态SQL。
declare @sql varchar(8000)
set @sql = 'select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [' + 课程 + ']'
from (select distinct 课程 from tb) as a
set @sql = @sql + ' , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名'
exec(@sql)
--SQL SERVER 2005 静态SQL。
select m.* , n.平均分 , n.总分 from
(select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b) m,
(select 姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名
--SQL SERVER 2005 动态SQL。
declare @sql varchar(8000)
select @sql = isnull(@sql + ',' , '') + 课程 from tb group by 课程
exec ('select m.* , n.平均分 , n.总分 from
(select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b) m ,
(select 姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名')
其他实例
http://topic.csdn.net/u/20100708/18/55df5a90-27a7-4452-a69a-27f735539a1f.html?seed=24842417&r=66831902#r_66831902
--3、不同数据按照序号转为列,方法基本同 1
if object_id('tb1') is not null drop table tb1
go
CREATE table tb1 --数据表
(
cpici varchar(10) not null,
cname varchar(10) not null,
cvalue int null
)
--插入测试数据
INSERT INTO tb1 values('T501','x1',31)
INSERT INTO tb1 values('T501','x1',33)
INSERT INTO tb1 values('T501','x1',5)
INSERT INTO tb1 values('T502','x1',3)
INSERT INTO tb1 values('T502','x1',22)
INSERT INTO tb1 values('T502','x1',3)
INSERT INTO tb1 values('T503','x1',53)
INSERT INTO tb1 values('T503','x1',44)
INSERT INTO tb1 values('T503','x1',50)
INSERT INTO tb1 values('T503','x1',23)
--在sqlserver2000里需要用自增辅助
alter table tb1 add id int identity
go
declare @s varchar(8000)
set @s='select cpici '
select @s=@s+',max(case when rn='+ltrim(rn)+' then cvalue end) as cvlue'+ltrim(rn)
from (select distinct rn from (select rn=(select count(1) from tb1 where cpici=t.cpici and id<=t.id) from tb1 t)a)t
set @s=@s+' from (select rn=(select count(1) from tb1 where cpici=t.cpici and id<=t.id),* from tb1 t
) t group by cpici'
exec(@s)
go
alter table tb1 drop column id
--再2005就可以用row_number
declare @s varchar(8000)
set @s='select cpici '
select @s=@s+',max(case when rn='+ltrim(rn)+' then cvalue end) as cvlue'+ltrim(rn)
from (select distinct rn from (select rn=row_number()over(partition by cpici order by getdate()) from tb1)a)t
set @s=@s+' from (select rn=row_number()over(partition by cpici order by getdate()),* from tb1
) t group by cpici'
exec(@s)
---结果
/*
cpici cvlue1 cvlue2 cvlue3 cvlue4
---------- ----------- ----------- ----------- -----------
T501 31 33 5 NULL
T502 3 22 3 NULL
T503 53 44 50 23
警告: 聚合或其他 SET 操作消除了空值。
(3 行受影响)
*/
--测试用
IF OBJECT_ID('[tb]') IS NOT NULL DROP TABLE [tb]
GO
create table tb(电话号码 varchar(15), 通话时长 int ,行业 varchar(10))
insert tb
select '13883633601', 10 ,'餐饮' union all
select '18689704236', 20 ,'物流' union all
select '13883633601', 20 ,'物流' union all
select '13883633601', 20 ,'汽车' union all
select '18689704236', 20 ,'医疗' union all
select '18689704236', 20 ,'it' union all
select '18689704236', 20 ,'汽车' union all
select '13883633601', 50 ,'餐饮'
go
declare @sql varchar(8000)
set @sql='select 电话号码,sum(通话时长) 通话总和'
select @sql=@sql+',max(case when rowid='+ltrim(rowid)+' then 行业 else '''' end) as [行业'+ltrim(rowid)+']'
from (select distinct rowid from (select (select count(distinct 行业) from tb where 电话号码=t.电话号码 and 行业<=t.行业) rowid
from tb t) a) b
set @sql=@sql+' from ( select * , (select count(distinct 行业) from tb where 电话号码=t.电话号码 and 行业<=t.行业) rowid
from tb t ) t group by 电话号码'
exec(@sql)
--结果
/*
(所影响的行数为 8 行)
电话号码 通话总和 行业1 行业2 行业3 行业4
--------------- ----------- ---------- ---------- ---------- ----------
13883633601 100 餐饮 汽车 物流
18689704236 80 it 汽车 物流 医疗
(所影响的行数为 2 行)
*/
另一种动态行转列:
http://topic.csdn.net/u/20100612/10/4CFCB667-89FA-4985-90D5-B8A420A6FF12.html
if object_id('[tb]') is not null drop table [tb]
go
create table [tb]([姓名] varchar(1),[部门] varchar(4),[学历] varchar(4),[出生年月] datetime)
insert [tb]
select 'A','后勤','高中','1986-1-1' union all
select 'B','后勤','初中','1984-3-7' union all
select 'C','管理','本科','1987-2-1' union all
select 'D','操作','专科','1976-2-1' union all
select 'E','操作','专科','1943-2-1'
go
GO
if object_id('GetGroupByCol') is not null drop proc GetGroupByCol
go
create PROCEDURE [dbo].[GetGroupByCol]
@colm nvarchar(100)
AS
declare @sql varchar(4000)
set @sql='
declare @sql varchar(8000)
set @sql=''select 部门''
select @sql =@sql+ '', sum(case ltrim('+@colm+') when ''''''+ltrim(' + @colm + ')+'''''' then 1 else 0 end)
[''+ltrim(' + @colm + ')+'']'' from (select distinct '+@colm+' from tb where '+@colm+' is not null) as a
set @sql = @sql + '' from tb group by 部门''
exec(@sql)'
exec(@sql)
GO
exec GetGroupByCol N'学历'
exec GetGroupByCol N'出生年月'
exec GetGroupByCol N'姓名'
/*
(所影响的行数为 5 行)
部门 本科 初中 高中 专科
---- ----------- ----------- ----------- -----------
操作 0 0 0 2
管理 1 0 0 0
后勤 0 1 1 0
(所影响的行数为 3 行)
部门 02 1 1943 12:00AM 02 1 1976 12:00AM 03 7 1984 12:00AM 01 1 1986 12:00AM 02 1 1987 12:00AM
---- ------------------ ------------------ ------------------ ------------------ ------------------
操作 1 1 0 0 0
管理 0 0 0 0 1
后勤 0 0 1 1 0
(所影响的行数为 3 行)
部门 A B C D E
---- ----------- ----------- ----------- ----------- -----------
操作 0 0 0 1 1
管理 0 0 1 0 0
后勤 1 1 0 0 0
(所影响的行数为 3 行)
*/
以下可参考的例子
1、普通多表联合
http://topic.csdn.net/u/20100623/00/077055eb-784d-4b27-8407-2c17adc06c60.html?seed=81934135&r=66426155#r_66426155
http://topic.csdn.net/u/20100622/19/9710803c-441b-45d0-b010-703a2633fe89.html?47161
2、多表根据时间 计算序号
http://topic.csdn.net/u/20100623/12/bbb0921b-0e1b-4435-8e85-959d87844954.html?seed=2145286087&r=66438763#r_66438763
http://topic.csdn.net/u/20100701/09/1684649b-b893-463b-8b40-7f4b894cd41e.html?seed=205688256&r=66630774#r_66630774
3、财务相关
http://topic.csdn.net/u/20100626/00/83499112-43ae-4caa-a1fd-268cc5138da6.html?seed=415671352&r=66513615#r_66513615
4、根据行数转列
http://topic.csdn.net/u/20100705/12/e325571b-c368-4174-859f-17ae708eca3d.html
http://topic.csdn.net/u/20100706/09/c34728dc-6167-45df-b7cf-974612b9aa8b.html
http://topic.csdn.net/u/20100706/16/f217deed-a2be-4950-b911-2624ac7a881a.html?39445
5、根据排序大小转
http://topic.csdn.net/u/20100707/13/63f4a02e-ebc3-4c71-9380-d6b2ca0eb366.html?39970
6、分组排序按序号转
http://topic.csdn.net/u/20100725/05/7f813114-c423-4759-97b8-b22e1e2e90d7.html?seed=471594449&r=67220945#r_67220945
Sql 行转列问题总结的更多相关文章
- SQL 行转列和列转行
SQL 行转列和列转行 行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过 ...
- Ms sql行转列。汇总
SQL行转列汇总 PIVOT 用于将列值旋转为列名(即行转列),在 SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT 的一般语法是:PIVOT(聚合函数(列) FOR 列 ...
- sql 行专列 列转行 普通行列转换
转载:http://www.cnblogs.com/newwind521/archive/2010/11/25/1887203.html sql 行专列 列转行 普通行列转换 /* 标题:普通行列转换 ...
- sql 行转列 PIVOT 列转行 UNPIVOT
原文:sql 行转列 PIVOT 列转行 UNPIVOT 一: 现有表一(t_table1),想转为表二(t_table2)的格式. 表一: 年 公司 收入 2013 公司1 12 2013 公司2 ...
- sql 行转列总结
原文:sql 行转列总结 PIVOT UNPIVOT的用法 PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...
- SQL行转列 (及EAV模型获取数据)
参考文章: http://www.williamsang.com/archives/1508.html 情景简介 学校里面记录成绩,每个人的选课不一样,而且以后会添加课程,所以不需要把所有课程当作列. ...
- SQL行转列,列转行
SQL 行转列,列转行 行列转换在做报表分析时还是经常会遇到的,今天就说一下如何实现行列转换吧. 行列转换就是如下图所示两种展示形式的互相转换 行转列 假如我们有下表: SELECT * FROM s ...
- sql 行转 列, 列转行
行列互转 复制代码 create table test(id ),quarter int,profile int) insert into test values(,,) insert into te ...
- SQL行转列和列转行
行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和 ...
随机推荐
- java几道简单的面试题目
1. 请问以下程序会输出什么? public class Test { public static void main(String[] args) { Par ...
- Android 常用工具类之 DimenUtil
public class DimenUtil { /** sp转换成px */ public static int sp2px(float spValue) { float fontScale = M ...
- 【JQGRID DOCUMENTATION】.学习笔记.3.Pager
处理大量数据时,一次只想显示一小部分.这时就需要Navigation Bar.目前Pager不能用于TreeGrid. 定义 }); 定义高度grid,pager是grid的一部分,宽度等于gird的 ...
- Could not write metadata for '/taiping-sol-insu-composite'.
Could not write metadata for '/taiping-sol-insu-composite'. 这是由于删除一个项目时,没有同时在硬盘上删除该项目,而后又到硬盘文件系统中删除了 ...
- wordpress网站被挂马以及防御方法
wordpress本身的安全性是非常的高的,一般不会被轻易的破解,被挂马,但是我们也不能够过度迷信wordpress的安全性,凡是连接上互联网的服务器和电脑,都存在被破解的风险性.所以我们在日常维护自 ...
- PHP正则表达式之定界符和原子介绍
1,正则表达式的定界符. 除了字母.数字和反斜线\以外的任何字符都可以为定界符号,比如 | |.//.{}.!!等等,但是需要注意,如果没有特殊需要,我们都使用正斜线//作为正则表达式的定界符号. 2 ...
- JS参数传值
1.JS获取URL参数值 //js获取url参数值 function request(paras) { var url = location.href; , url.length).split(&qu ...
- ACM题目————星际之门(一)
描述 公元3000年,子虚帝国统领着N个星系,原先它们是靠近光束飞船来进行旅行的,近来,X博士发明了星际之门,它利用虫洞技术,一条虫洞可以连通任意的两个星系,使人们不必再待待便可立刻到达目的地. 帝国 ...
- Java内部类、静态嵌套类、局部内部类、匿名内部类
Nested classes are further divided into two types: static nested classes: If the nested class is sta ...
- JAVA基础知识之Collections工具类
排序操作 Collections提供以下方法对List进行排序操作 void reverse(List list):反转 void shuffle(List list),随机排序 void sort( ...