SQL中几种行变列的情况
来源:互联网 发布:曾志豪 知乎 编辑:程序博客网 时间:2024/04/30 03:31
/*有三个数据库表, 一个是学生表S(SNO,SNAME),字段分别表示学号,姓名; 一个是课程表C(CNO,CNAME),字段分别表示课程号,课程名称; 一个是成绩表T(SNO,CNO,SCORE),字段分别表示学号,课程号,该学生该课程成绩。
现在要实现这个表:
姓名 语文 数学 英语 物理 化学 ... 张三 分数 分数 分数 分数 分数 李四 分数 分数 分数 分数 分数 王五 分数 分数 分数 分数 分数 ...
*/
T-SQL
f object_id('s') is not null drop table s if object_id('c') is not null drop table c if object_id('t') is not null drop table t create table S(sno int,sname varchar(300)) create table c(cno int,cname varchar(300)) create table t(sno int,cno int,score int) insert into S(sno,sname) select 1,'张三' union select 2,'李四' union select 3,'王五' union select 4,'甲六' insert into c(cno,cname) select 1,'语文' union select 2,'数学' union select 3,'英语' union select 4,'物理' union select 5,'化学' union select 6,'历史' union select 7,'历史' insert into t(SNO,CNO,score) select 1,1,80 union select 1,2,70 union select 1,3,50 union select 1,4,60 union select 1,5,90 union select 1,6,60 union select 2,1,41 union select 2,2,42 union select 2,3,53 union select 2,4,64 union select 3,1,43 union select 3,2,44 union select 3,3,55 union select 3,4,66 /**//*使用动态SQL语句*/ declare @abc varchar(3000) set @abc = '' select @abc = @abc + ',min( case when cno = '+ cast(cno as varchar(8)) +' then score end ) as '''+cname+ '''' from c declare @sql varchar(3000) set @sql = 'select (select sname from S where S.sno= T.sno ) as sname '+@abc +' from T group by sno' exec (@sql) /**//* 不使用动态SQL语句*/ select sname 姓名, max(yw) 语文, max(sx) 数学, max(yy) 英语, max(wl) 物理, max(hx) 化学, max(ls) 历史 from ( select sname ,(case when cname='语文' then score end) yw, (case when cname='数学' then score end) sx, (case when cname='英语' then score end) yy, (case when cname='物理' then score end) wl, (case when cname='化学' then score end) hx, (case when cname='历史' then score end) ls from t left join s on t.sno=s.sno left join c on t.cno=c.cno ) tmp group by sname
有如图A所示的表stat,表的内容为各个班级拥有水果的数量,要求将表stat的查询结果以图B的形式显示。
class fruit amount ----------------------------- class a apple 30 class a pear 15 class b apple 40 class b pear 20 图 A
class apple_amount pear_amount ---------------------------- class a 30 15 class b 40 20 图 B
T-SQL
create table stat(class varchar(30), fruit varchar(30), amount int) insert into stat (class,fruit,amount) select 'class a', 'apple', 30 union select 'class a', 'pear', 15 union select 'class b', 'apple', 40 union select 'class b', 'pear', 20 union select 'class a','apple',11 union select 'class b','apple',12 select * from stat select class, sum(apple_amount) apple_amount, sum(pear_amount) pear_amount from ( select class, (case when fruit='apple' then amount else 0 end) as apple_amount, (case when fruit='pear' then amount else 0 end) as pear_amount from stat ) tmp group by class
PL/SQL
create table stat(class varchar2(30), fruit varchar2(30), amount number(10)); insert into stat(class, fruit, amount) values('class a', 'apple', 30); insert into stat(class, fruit, amount) values('class a', 'pear', 15); insert into stat(class, fruit, amount) values('class b', 'apple', 40); insert into stat(class, fruit, amount) values('class b', 'pear', 20); commit; select class, sum(apple_amount) apple_amount, sum(pear_amount) pear_amount from ( select class, decode(fruit, 'apple', amount, 0) apple_amount, decode(fruit, 'pear', amount, 0) pear_amount from stat ) group by class
存储过程
/**//*范例表 create table 表1 ( 號數 char(10), 成績 integer, 科目 char(10) ) insert into 表1 select '1',60,'数学' union select '1',43,'物理' union select '1',100,'语文' union select '2',87,'语文' union select '2',99,'数学' union select '2',89,'物理' union select '2',87,'语文' */ Create procedure RowToColumn @Table varchar(30), --表名 @MasterField varchar(30), --待转名称列名 char字段 @SlaveField varchar(30), --待转数据列名 int型字段 @GroupID varchar(30) --分组ID as --调用方法 RowToColumn '表1','科目','成績','號數' begin DECLARE @mSQL VARCHAR(8000) set @msql = 'DECLARE @SQL VARCHAR(8000)' set @msql = @msql + ' set @SQL= ''select ' + @GroupID + '''' set @msql = @msql + ' SELECT @SQL= @SQL+'',max(CASE WHEN ' + @MasterField + '=''''''+' + @MasterField + '+'''''' then ' + @SlaveField + ' else 0 end )[''+' + @MasterField + '+'']'' from(select distinct ' + @MasterField + ' from ' + @Table + ') a' set @msql = @msql + ' SET @SQL=@SQL+ '' from ' + @Table + ' group by ' + @GroupID + '''' set @msql = @msql + ' exec(@SQL)' exec(@msql) end
分组行转列
/**//*1. 表格A原始数据如下:*/ CREATE TABLE [dbo].[A] ( [C1] [varchar] (50) COLLATE Chinese_PRC_CS_AS NULL , [C2] [varchar] (50) COLLATE Chinese_PRC_CS_AS NULL , [C3] [varchar] (50) COLLATE Chinese_PRC_CS_AS NULL , [C4] [varchar] (50) COLLATE Chinese_PRC_CS_AS NULL ) insert into A ('95533','SZ','44','123000') insert into A ('95566','SZ','44','233300') insert into A ('95588','GZ','44','4566') insert into A ('95599','GZ','44','456666') insert into A ('95533','ZH','44','333333') insert into A ('95577','DG','44','555555') insert into A ('95588','ST','44','44444') /**//*2. 分组行变列 处理数据:*/ DECLARE @SQL VARCHAR(4000) SET @SQL='SELECT C2' SELECT @SQL= @SQL+ ',max(CASE WHEN C1 = ''' + C1 + ''' THEN C4 ELSE 0 END) ['+C1+']' FROM (SELECT DISTINCT C1 FROM A) TAB SET @SQL=@SQL+ ' FROM A GROUP BY C2' EXEC (@SQL) /**//*得到如下结果: */ C2 95533 95566 95577 95588 95599 -------------------------------------------- DG 0 0 555555 0 0 GZ 0 0 0 4566 456666 ST 0 0 0 44444 0 SZ 123000 233300 0 0 0 ZH 333333 0 0 0 0 OK, 分组就这样完成了. 参考经典实例: /**//* 实例一 create table t (id int identity,name varchar(10),code int) insert t values('人口',20) insert t values('经济',12) insert t values('文化',15) insert t values('土地',45) declare @sql varchar(1000) set @sql = '' select @sql = @sql+name+'=max(case when name='''+name+''' then code else null end),' from t --print @sql set @sql = left(@sql,len(@sql) - 1) set @sql = 'select [姓名]=''年龄'', '+@sql+' from t' exec (@sql) --drop table t 实例二 create table #(a varchar(100),b int) insert # values('aa',11) insert # values('bb',1) insert # values('aa',45) insert # values('cc',81) insert # values('a',11) insert # values('aay',561) insert # values('a',14) declare @sql varchar(8000) set @sql = 'select ' select @sql = @sql + 'sum(case a when '''+a+''' then b else 0 end) '+a+'的数量,' from (select distinct a from #) as a select @sql = left(@sql,len(@sql)-1) + ' from #' exec(@sql) -- drop table # */
--行列互转/******************************************************************************************************************************************************以学生成绩为例子,比较形象易懂整理人:中国风(Roy)日期:2008.06.06******************************************************************************************************************************************************/--1、行互列--> --> (Roy)生成測試數據 if not object_id('Class') is null drop table ClassGoCreate table Class([Student] nvarchar(2),[Course] nvarchar(2),[Score] int)Insert Classselect N'张三',N'语文',78 union allselect N'张三',N'数学',87 union allselect N'张三',N'英语',82 union allselect N'张三',N'物理',90 union allselect N'李四',N'语文',65 union allselect N'李四',N'数学',77 union allselect N'李四',N'英语',65 union allselect N'李四',N'物理',85 Go--2000方法:动态:declare @s nvarchar(4000)set @s=''Select @s=@s+','+quotename([Course])+'=max(case when [Course]='+quotename([Course],'''')+' then [Score] else 0 end)'from Class group by[Course]exec('select [Student]'+@s+' from Class group by [Student]')生成静态:select [Student], [数学]=max(case when [Course]='数学' then [Score] else 0 end), [物理]=max(case when [Course]='物理' then [Score] else 0 end), [英语]=max(case when [Course]='英语' then [Score] else 0 end), [语文]=max(case when [Course]='语文' then [Score] else 0 end) from Class group by [Student]GO动态:declare @s nvarchar(4000)Select @s=isnull(@s+',','')+quotename([Course]) from Class group by[Course]exec('select * from Class pivot (max([Score]) for [Course] in('+@s+'))b')生成静态:select * from Class pivot (max([Score]) for [Course] in([数学],[物理],[英语],[语文]))b生成格式:/*Student 数学 物理 英语 语文------- ----------- ----------- ----------- -----------李四 77 85 65 65张三 87 90 82 78(2 行受影响)*/------------------------------------------------------------------------------------------go--加上总成绩(学科平均分)--2000方法:动态:declare @s nvarchar(4000)set @s=''Select @s=@s+','+quotename([Course])+'=max(case when [Course]='+quotename([Course],'''')+' then [Score] else 0 end)'from Class group by[Course]exec('select [Student]'+@s+',[总成绩]=sum([Score]) from Class group by [Student]')--加多一列(学科平均分用avg([Score]))生成动态:select [Student], [数学]=max(case when [Course]='数学' then [Score] else 0 end), [物理]=max(case when [Course]='物理' then [Score] else 0 end), [英语]=max(case when [Course]='英语' then [Score] else 0 end), [语文]=max(case when [Course]='语文' then [Score] else 0 end), [总成绩]=sum([Score]) --加多一列(学科平均分用avg([Score]))from Class group by [Student]go--2005方法:动态:declare @s nvarchar(4000)Select @s=isnull(@s+',','')+quotename([Course]) from Class group by[Course] --isnull(@s+',','') 去掉字符串@s中第一个逗号exec('select [Student],'+@s+',[总成绩] from (select *,[总成绩]=sum([Score])over(partition by [Student]) from Class) a pivot (max([Score]) for [Course] in('+@s+'))b ')生成静态:select [Student],[数学],[物理],[英语],[语文],[总成绩] from (select *,[总成绩]=sum([Score])over(partition by [Student]) from Class) a --平均分时用avg([Score])pivot (max([Score]) for [Course] in([数学],[物理],[英语],[语文]))b 生成格式:/*Student 数学 物理 英语 语文 总成绩------- ----------- ----------- ----------- ----------- -----------李四 77 85 65 65 292张三 87 90 82 78 337(2 行受影响)*/go--2、列转行--> --> (Roy)生成測試數據 if not object_id('Class') is null drop table ClassGoCreate table Class([Student] nvarchar(2),[数学] int,[物理] int,[英语] int,[语文] int)Insert Classselect N'李四',77,85,65,65 union allselect N'张三',87,90,82,78Go--2000:动态:declare @s nvarchar(4000)select @s=isnull(@s+' union all ','')+'select [Student],[Course]='+quotename(Name,'''')--isnull(@s+' union all ','') 去掉字符串@s中第一个union all+',[Score]='+quotename(Name)+' from Class'from syscolumns where ID=object_id('Class') and Name not in('Student')--排除不转换的列order by Colidexec('select * from ('+@s+')t order by [Student],[Course]')--增加一个排序生成静态:select * from (select [Student],[Course]='数学',[Score]=[数学] from Class union all select [Student],[Course]='物理',[Score]=[物理] from Class union all select [Student],[Course]='英语',[Score]=[英语] from Class union all select [Student],[Course]='语文',[Score]=[语文] from Class)t order by [Student],[Course]go--2005:动态:declare @s nvarchar(4000)select @s=isnull(@s+',','')+quotename(Name)from syscolumns where ID=object_id('Class') and Name not in('Student') order by Colidexec('select Student,[Course],[Score] from Class unpivot ([Score] for [Course] in('+@s+'))b')goselect Student,[Course],[Score] from Class unpivot ([Score] for [Course] in([数学],[物理],[英语],[语文]))b生成格式:/*Student Course Score------- ------- -----------李四 数学 77李四 物理 85李四 英语 65李四 语文 65张三 数学 87张三 物理 90张三 英语 82张三 语文 78(8 行受影响)*/
- SQL中几种行变列的情况
- SQL中几种行变列的情况
- 解决 SQL Server 耗尽内存的情况
- 清点数据库Job情况的SQL语句
- 解决 SQL Server 耗尽内存的情况
- sql中用到in的一种情况
- SQL Server2005 表的使用情况监控
- SQL 动态排序的部分情况实现
- oralce显示tablespace使用情况的sql
- sql语句交集情况的查询技巧
- SQL 查看死锁情况的存储过程
- ORACLE空间使用情况统计的SQL
- 查看表空间占用情况的SQL
- 查看表空间使用情况的sql
- Scripts:报告dbtime的情况dbtime.sql
- sql查询in包含null的情况
- sql case when 中遇到的情况
- SQL查询索引失效的情况
- Collection List Set Map 区别记忆
- 走进Zend Framework框架编程(六):视图(2)
- sfo获取文件夹列表
- 生成图片验证码
- C# 的线程
- SQL中几种行变列的情况
- ace 日志配置策略例子
- 对方网络非正常断开检测方法
- JS笔记
- Compuware收购Proxima
- php xml Input is not proper UTF-8, indicate encoding错误
- Visual Studio 2008 新特性一览
- 内存映射文件探讨
- 为什么要使用集合类