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 @[email protected]+‘,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 @[email protected]+‘ 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 @[email protected]+‘,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 @[email protected]+‘ 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 @[email protected]+‘,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 @[email protected]+‘ 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 [email protected]+ ‘‘, sum(case ltrim(‘[email protected]+‘) when ‘‘‘‘‘‘+ltrim(‘ + @colm + ‘)+‘‘‘‘‘‘ then 1 else 0 end)

[‘‘+ltrim(‘ + @colm + ‘)+‘‘]‘‘ from (select distinct ‘[email protected]+‘ from tb where ‘[email protected]+‘ 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

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lxl743p/article/details/45146551

时间: 2024-10-28 13:32:21

SQL行转列经典例子(转载)的相关文章

SQL 行转列

---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(

重温SQL——行转列,列转行

行转列,列转行是我们在开发过程中经常碰到的问题.行转列一般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER 2005 新增的运算符PIVOT来实现.用传统的方法,比较好理解.层次清晰,而且比较习惯. 但是PIVOT .UNPIVOT提供的语法比一系列复杂的SELECT...CASE 语句中所指定的语法更简单.更具可读性.下面我们通过几个简单的例子来介绍一下列转行.行转列问题. 我们首先先通过一个老生常谈的例子,学生成绩表(下面简化了些)来形象了解下行转列 CREATE TAB

SQL——行转列,列转行

行转列,列转行是我们在开发过程中经常碰到的问题.行转列一般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER 2005 新增的运算符PIVOT来实现.用传统的方法,比较好理解.层次清晰,而且比较习惯. 但是PIVOT .UNPIVOT提供的语法比一系列复杂的SELECT...CASE 语句中所指定的语法更简单.更具可读性.下面我们通过几个简单的例子来介绍一下列转行.行转列问题. 我们首先先通过一个老生常谈的例子,学生成绩表(下面简化了些)来形象了解下行转列 CREATE TAB

sql 行专列 列转行 普通行列转换

转载:http://www.cnblogs.com/newwind521/archive/2010/11/25/1887203.html sql 行专列 列转行 普通行列转换 /* 标题:普通行列转换(version 2.0) 作者:爱新觉罗.毓华 时间:2008-03-09 地点:广东深圳 说明:普通行列转换(version 1.0)仅针对sql server 2000提供静态和动态写法,version 2.0增加sql server 2005的有关写法.  问题:假设有张学生成绩表(tb)如

重温SQL&mdash;&mdash;行转列,列转行

下面来了一个统计数据的需求,要求按日期.支付方式来统计充值金额信息.这也是一个典型的行转列的例子.我们可以通过下面的脚本来达到目的 代码 SELECT CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime,        CASE PayType WHEN '支付宝'     THEN SUM(Money) ELSE 0 END AS '支付宝',        CASE PayType WHEN '手机短信'    THEN SUM(Money

SQL 行转列查询汇总

SQL行转列汇总 PIVOT 用于将列值旋转为列名(即行转列),在 SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT 的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P 注意:PIVOT.UNPIVOT是SQL Server 2005 的语法,使用需修改数据库兼容级别(在数据库属性->选项->兼容级别改为 90 ) SQL2008 中可以直接使用 完整语法: table_source PIVOT( 聚合函数(value_column) F

Sql 行转换为列 以及列转换为行的心得

这是 创建数据库的脚本文件 CREATE TABLE [dbo].[stu]( [学号] [nvarchar](255) NOT NULL, [姓名] [nvarchar](255) NULL, [性别] [nvarchar](255) NULL, [专业] [nvarchar](255) NULL, [院系] [nvarchar](255) NULL ) ON [PRIMARY] GO INSERT [dbo].[stu] ([学号], [姓名], [性别], [专业], [院系]) VALU

SQL行转列汇总

SQL行转列汇总 PIVOT 用于将列值旋转为列名(即行转列),在 SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT 的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P 注意:PIVOT.UNPIVOT是SQL Server 2005 的语法,使用需修改数据库兼容级别(在数据库属性->选项->兼容级别改为   90 ) SQL2008 中可以直接使用 完整语法: table_source PIVOT( 聚合函数(value_column)

sql 行转列总结

原文:sql 行转列总结 PIVOT UNPIVOT的用法 PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (-) )AS P 完整语法: table_source PIVOT( 聚合函数(value_column) FOR pivot_column IN(<column_list>) ) UNPIVOT用于将列明转为列值(即列转行),在SQL Server 2