`
JavaSam
  • 浏览: 951835 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

sql行转列解决方案

    博客分类:
  • 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

1
2
分享到:
评论

相关推荐

    sql行转列解决方案.

    标题与描述均提到“SQL行转列解决方案”,这主要指的是在SQL中将数据表中的行数据转换为列数据的一种操作技巧,通常应用于需要对多行数据进行汇总展示或数据分析的场景。这种转换对于数据报告、统计分析等业务需求至...

    Sql,oracle数据表行转列问题

    SQL行转列问题解决方案 SQL行转列问题是指将行记录转换为列记录的操作。本文将详细讲解SQL行转列问题的解决方案,并提供了一个具体的实例来帮助读者更好地理解该问题。 问题描述 假设我们有一个学生成绩表tb,...

    sql列转行以及行转列的通用存储过程

    ### 标题解析:SQL列转行及行转列的通用存储过程 该标题表明文章主要介绍在SQL中如何通过一个通用的存储过程实现列数据转化为行数据(列转行),或者反过来将行数据转化为列数据(行转列)。这两种转换方式在处理多...

    mysql复杂动态行转列解决方案

    总的来说,虽然MySQL没有内置的动态行转列功能,但通过灵活运用现有函数和SQL语句,我们可以构建出满足需求的解决方案。在实际工作中,应根据数据规模和业务需求来选择最适合的方法,确保数据处理的效率和准确性。在...

    oracle行转列较精典的解决方案

    ### Oracle行转列的经典解决方案 在Oracle数据库管理与开发过程中,经常会遇到需要将数据表中的行数据转换为列数据的情况,这种操作被称为“行转列”或者“行列转换”。行列转换是数据分析、报表生成等场景中非常...

    Oracle行转列(不定列)

    本篇文章将详细探讨Oracle如何实现行转列为列的过程,以及在面对不确定列数时的解决方案。 在传统的SQL查询中,数据通常是以行的形式存储和展示。然而,在某些场景下,我们可能需要将同一类别的数据从多行转换为一...

    oracle 行转列

    ### Oracle 行转列知识点详解 #### 一、Oracle 行转列概念及应用场景 在数据库操作中,经常需要对...无论是固定列数还是动态列数的情况,都有相应的解决方案。掌握这些方法有助于更好地应对实际工作中的各种需求。

    SqlServer列转行的另一种方式

    常见的转换包括列转行、行转列等操作。通常我们使用`PIVOT`和`UNPIVOT`来实现这些转换,但在某些场景下可能需要采用更为灵活的方法。本文将介绍一种利用`FOR XML PATH`来实现列转行的操作方法,并通过示例代码进行...

    SQL行转列和列转行代码详解

    在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和总结过。为了加深认识,再总结一次。 行列互转,可以分为静态互转,即事先就知道要处理多少行(列);动态互转,事先不知道处理多少行(列)...

    t-sql编程行列转换(静态和动态)

    t-sql编程实现静态和动态的行转列、列转行代码

    SQL Server系统调优解决方案

    SQL Server系统调优解决方案主要关注的是如何通过优化数据库的索引来提升系统性能。索引是数据库性能的关键因素,它们能够加速数据检索、提高查询效率、加快表间连接速度以及减少排序和分组所需的时间。 首先,索引...

    sql server 2008 将一列值转换成一个字符串

    ### 二、示例场景与解决方案 假设我们有一个名为`entp`的表,其中包含一个名为`innerID`的整数字段,现在我们需要将这个字段的所有值转换为一个由逗号分隔的字符串。 #### SQL语句实现 下面的SQL语句展示了如何...

    SQL性能优化解决方案

    "SQL性能优化解决方案"着重关注如何发现并解决数据库系统的性能问题,这不仅涉及查询效率,还包括数据处理、存储和并发控制等多个方面。下面将详细介绍如何进行SQL性能优化,并以DMV(动态管理视图)脚本为例,阐述...

    sql转access集锦

    本篇文章主要探讨如何将SQL Server数据库转换为Microsoft Access数据库,以及在这个过程中可能会遇到的一些问题及其解决方案。 首先,我们从SQL Server转换到Access的基本步骤开始: 1. 使用SQL Server Enterprise...

    Oracle 9i Java程序设计—使用PL_SQL和Java的解决方案

    《Oracle 9i Java程序设计—使用PL_SQL和Java的解决方案》是一本专注于在Oracle数据库环境中结合使用Java和PL/SQL进行程序开发的专著。这本书面向的是对Oracle数据库有基础了解,希望深入学习如何利用Java和PL/SQL...

    SQL 混合数据导入丢失解决方案.docx

    ### SQL Server导入Excel数据时混合数据丢失问题及解决方案 #### 一、问题概述 在将Excel数据导入到SQL Server数据库的过程中,经常会遇到由于数据类型的不匹配或者格式问题导致的数据丢失现象。这种问题不仅会影响...

    数据库动态生成列数据库纵向列转横向列

    #### 解决方案 ##### 1. SQL Server 2000 在SQL Server 2000中,我们可以使用`CASE`语句结合`MAX`函数和`GROUP BY`来实现这一转化。具体步骤如下: - **创建表结构**: ```sql CREATE TABLE tb (name VARCHAR(10...

    sqlserver导出excel文件出错解决方案

    ### SQL Server 导出 Excel 文件出错解决方案 在日常工作中,我们经常需要将 SQL Server 数据库中的数据导出到 Excel 文件以便进一步分析或共享。然而,在执行这一操作时,可能会遇到错误代码 0x800A0E7A 和 0x...

    自增字段的SQL语句解决方案

    ### 自增字段的SQL语句解决方案 在数据库设计与管理中,自增字段是一个非常实用的功能,它能够自动为每一条新记录分配一个唯一的、连续的整数值。这对于需要唯一标识符(例如主键)的场景特别有用。本文将详细介绍...

Global site tag (gtag.js) - Google Analytics