`

sql 行转列 简单易懂

阅读更多
摘自:http://blog.csdn.net/xys_777/archive/2010/06/22/5685953.aspx

阅:经验证,可运行;

行转列问题总结 - 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



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xys_777/archive/2010/06/22/5685953.aspx
分享到:
评论

相关推荐

    sql入门-最简单易懂的数据库书法教程

    本教程旨在提供一个简单易懂的SQL入门指南,适合初学者快速掌握基础概念。 首先,我们需要了解数据库管理系统(DBMS),它是一个用于创建、管理和操作数据库的软件系统。在SQL中,我们通过数据定义语言(DDL)来...

    论坛T-SQL语句实例 简单易懂 建库建表建约束等

    本资源针对初学者,通过"论坛T-SQL语句实例 简单易懂 建库建表建约束等"这个主题,旨在帮助初学者快速理解和掌握T-SQL的基础操作。 首先,我们来讨论如何创建数据库。在T-SQL中,使用`CREATE DATABASE`语句可以新建...

    sql2008用SQL语言 将EXCEL文件导入数据库(简单易懂

    接下来,假设我们有一个名为`test1.xls`的Excel文件,其第一行包含字段名,而其余行包含数据。我们可以使用以下SQL语句将数据导入到已存在的数据库表`Table_1`中: ```sql USE [数据库名称]; -- 使用目标数据库 ...

    简单易懂的sql安全设置和基础

    简单易懂的sql安全设置和基础 规律:数字不用单引号,字符用单引号 选择 1. 假设有一个名为email_table 的表,包含名字和地址两个字段,要得到Bill Gates 的e_mail地址,你可以使用下面的查询: SELECT email from ...

    简单实用的SQL语句大全

    本资料“简单实用的SQL语句大全”旨在为初学者提供一个全面且易懂的SQL学习指南,涵盖了基本语法、函数、操作以及高级查询技巧。 1. **SQL基础** - **数据类型**:SQL支持多种数据类型,如整数(INT)、浮点数...

    SQL语句培训教材

    《SQL语句培训教材》是一本专为初学者设计的指南,旨在全面解析SQL语句的使用,通过经典实例和简单易懂的解释,帮助读者快速掌握SQL的基础知识。SQL,即Structured Query Language,是数据库管理和操作的核心工具,...

    ebook.Practical_SQL_Handbook_Using_SQL_Variants.0201703092

    SQL的核心在于其简洁明了的语法,使得数据库操作变得简单易懂。 1. 数据查询:SQL的SELECT语句是其最常用的部分,用于从数据库中检索信息。你可以通过指定列名、表名、条件和排序方式来定制查询。例如,`SELECT ...

    通俗易懂的数据库设计技巧

    "通俗易懂的数据库设计技巧"这一主题旨在帮助初学者和经验不足的开发者掌握数据库设计的核心概念,通过实用的方法和清晰的解释,使复杂的理论变得简单易懂。 一、关系型数据库基础 1. 关系模型:数据库设计的基础是...

    比较详细实用的SQL语法、实例手册,简单明了,资料完整,必备工具书。

    关系数据库由一个或多个表格组成,每个表格包含列和行,列定义数据类型,行存储具体数据。 2. SQL语句分类:SQL主要分为DDL(Data Definition Language)、DML(Data Manipulation Language)、DQL(Data Query ...

    Oracle课堂笔记常用命令,简单易懂

    **标题**: Oracle课堂笔记常用命令,简单易懂 **描述**: oracle课堂笔记常用命令,适合初学者。 在学习Oracle时,掌握一些基本的操作命令对于日常的数据库管理和维护非常重要。以下是一些常用的环境配置与基础命令...

    SQL课件

    它以简单易懂的方式进行讲解,并通过具体的实例帮助学习者深入理解SQL的核心概念。 SQL的主要功能包括数据查询、数据更新、数据插入和数据删除,同时也支持创建和管理数据库结构,如表、视图、索引等。以下是一些...

    jsp分页技术 简单易懂

    例如,在Oracle中,可以利用`ROWNUM`伪列进行分页;MySQL使用`LIMIT`子句;DB2使用`rownumber()`函数;SQL Server则有其他方式。 为了简化分页实现,可以使用工具类。以下是一个简化的示例: - **PagedStatement**...

    SQL Server 2005新功能之PIVOT的描述

    在SQL Server 2000及其以前版本,如果需要将数据的某列值转换为行对应的列,通常需要使用复杂的CASE语句配合聚合函数(如SUM)来实现,对于列值不确定的情况,还需要动态构建SQL语句。但PIVOT运算符的引入,极大地...

    在SQL查询中不使用语句SELECT 所有的列的7个原因

    2. **明确性**:指定需要的列,让SQL语句更清晰易懂,也便于后期维护。想象一下,几年后回看代码,你能迅速知道每列数据的用途吗? 3. **安全性**:避免暴露不必要的敏感信息,比如用户密码等字段,即使它们不在当前...

    sql初学者指南(sql语句示意图)

    本指南将引导初学者逐步理解SQL的基础知识,通过图形化的解释,使学习过程更为直观易懂。 ### 一、SQL语句的标准图 SQL语句主要包括以下几种类型: 1. **数据查询语言 (DQL)**:用于从数据库中检索数据,如`...

    SQL根据表中某列队值选择关联不同的表

    - **使用`UNION`操作**则更适合于简单的情况,特别是当查询涉及的表较少、条件简单时,这种方式更加直观易懂。 以上就是根据表中某列对值选择关联不同表的两种实现方法,可以根据实际业务场景和个人喜好选择适合的...

    sql子查询说明

    - **可读性**:子查询有时会使得SQL语句显得更为简洁易懂,尤其是当查询逻辑较为复杂时。 - **适用场景**:子查询更适合于处理简单查询或当连接查询难以实现时使用。 #### 六、子查询的最佳实践 1. **尽量避免使用...

    SQL数据库可视化工具

    SQL数据库可视化工具是一种高效且直观的方式来管理和操作数据库系统,它为用户提供了一种图形化的界面,使得复杂的SQL查询和数据库管理任务变得更为简单易懂。这些工具通常具备多种功能,包括但不限于浏览数据库结构...

    SQL查询工具

    综上所述,SQL查询工具通过其用户友好的界面和丰富的功能,降低了SQL学习的门槛,使数据库管理变得更加简单和高效。"数据库查询工具xquery.exe"可能是该工具的可执行文件,用户下载并运行后,即可开始体验这些强大的...

Global site tag (gtag.js) - Google Analytics