`
tcl1122
  • 浏览: 29743 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

sql中 行转列 (一)

阅读更多
近一段时间一直没怎么看过sql了,突袭一下:

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

INSERTINTO[StudentScores]SELECT'Nick','语文',80

INSERTINTO[StudentScores]SELECT'Nick','数学',90

INSERTINTO[StudentScores]SELECT'Nick','英语',70

INSERTINTO[StudentScores]SELECT'Nick','生物',85

INSERTINTO[StudentScores]SELECT'Kent','语文',80

INSERTINTO[StudentScores]SELECT'Kent','数学',90

INSERTINTO[StudentScores]SELECT'Kent','英语',70

INSERTINTO[StudentScores]SELECT'Kent','生物',85


现在想知道每位学生的每科成绩,而且每个学生的全部成绩排成一行,这样方便查看、统计,导出数据
SELECT UserName,MAX( CASE Subject WHEN'语文'THEN Score ELSE 0 END)AS '语文',
MAX(CASE Subject WHEN'数学'THEN Score ELSE 0 END)AS'数学',
MAX(CASE Subject WHEN'英语'THEN Score ELSE 0 END)AS'英语',
MAX(CASE Subject WHEN'生物'THEN Score ELSE 0 END)AS'生物' from
[StudentScores]
GROUP BY UserName




有一个游戏玩家充值表(仅仅为了说明,举的一个小例子),

代码

CREATETABLE[Inpours]
(
[ID]INTIDENTITY(1,1),
[UserName] NVARCHAR(20),--游戏玩家
[CreateTime]DATETIME,--充值时间
[PayType]NVARCHAR(20),--充值类型
[Money] DECIMAL,--充值金额
[IsSuccess] BIT,--是否成功1表示成功,0表示失败
CONSTRAINT[PK_Inpours_ID]PRIMARYKEY(ID)
)

INSERTINTOInpoursSELECT'张三','2010-05-01','支付宝',50,1

INSERTINTOInpoursSELECT'张三','2010-06-14','支付宝',50,1

INSERTINTOInpoursSELECT'张三','2010-06-14','手机短信',100,1

INSERTINTOInpoursSELECT'李四','2010-06-14','手机短信',100,1

INSERTINTOInpoursSELECT'李四','2010-07-14','支付宝',100,1

INSERTINTOInpoursSELECT'王五','2010-07-14','工商银行卡',100,1

INSERTINTOInpoursSELECT'赵六','2010-07-14','建设银行卡',100,1


统计数据的需求,要求按日期、支付方式来统计充值金额信息,脚本如下:



SELECT
CreateTime,
ISNULL(SUM([支付宝]),0)AS[支付宝],
ISNULL(SUM([手机短信]),0)AS[手机短信],
ISNULL(SUM([工商银行卡]),0)AS[工商银行卡],
ISNULL(SUM([建设银行卡]),0)AS[建设银行卡]
FROM
(
SELECT CONVERT(VARCHAR(10),CreateTime,120)AS CreateTime,
CASE PayType WHEN'支付宝'THEN SUM(Money)ELSE 0 END AS'支付宝',
CASE PayType WHEN'手机短信'THEN SUM(Money)ELSE 0 END AS'手机短信',
CASE PayType WHEN'工商银行卡'THEN SUM(Money)ELSE 0 END AS'工商银行卡',
CASE PayType WHEN'建设银行卡'THEN SUM(Money)ELSE 0 END AS'建设银行卡'
FROM Inpours
GROUP BY CreateTime,PayType
)T
GROUP BY CreateTime

其实行转列,关键是要理清逻辑,而且对分组(Group by)概念比较清晰。上面两个列子基本上就是行转列的类型了。但是有个问题来了,上面是我为了说明弄的一个简单列子。实际中,可能支付方式特别多,而且逻辑也复杂很多,可能涉及汇率、手续费等等(曾经做个这样一个),如果支付方式特别多,我们的CASE WHEN 会弄出一大堆,确实比较恼火,而且新增一种支付方式,我们还得修改脚本如果把上面的脚本用动态SQL改写一下,我们就能轻松解决这个问题

DECLARE@cmdTextVARCHAR(8000);
DECLARE@tmpSqlVARCHAR(8000);

SET@cmdText='SELECTCONVERT(VARCHAR(10),CreateTime,120)ASCreateTime,'+CHAR(10);
SELECT@cmdText=@cmdText+'CASEPayTypeWHEN'''+PayType+'''THENSUM(Money)ELSE0ENDAS'''+PayType
+''','+CHAR(10)FROM(SELECTDISTINCTPayTypeFROMInpours)T

SET@cmdText=LEFT(@cmdText,LEN(@cmdText)-2)--注意这里,如果没有加CHAR(10)则用LEFT(@cmdText,LEN(@cmdText)-1)

SET@cmdText=@cmdText+'FROMInpoursGROUPBYCreateTime,PayType';

SET@tmpSql='SELECTCreateTime,'+CHAR(10);
SELECT@tmpSql=@tmpSql+'ISNULL(SUM('+PayType+'),0)AS'''+PayType+''','+CHAR(10)
FROM(SELECTDISTINCTPayTypeFROMInpours)T

SET@tmpSql=LEFT(@tmpSql,LEN(@tmpSql)-2)+'FROM('+CHAR(10);

SET@cmdText=@tmpSql+@cmdText+')TGROUPBYCreateTime';
PRINT@cmdText
EXECUTE(@cmdText);

下面是通过PIVOT来进行行转列的用法
SELECT
CreateTime,[支付宝],[手机短信],
[工商银行卡],[建设银行卡]
FROM
(
SELECTCONVERT(VARCHAR(10),CreateTime,120)ASCreateTime,PayType,Money
FROMInpours
)P
PIVOT(
SUM(Money)
FORPayTypeIN
([支付宝],[手机短信],[工商银行卡],[建设银行卡])
)AST
ORDERBYCreateTime

有时可能会出现这样的错误:

消息 325,级别 15,状态 1,第 9 行

'PIVOT' 附近有语法错误。您可能需要将当前数据库的兼容级别设置为更高的值,以启用此功能。有关存储过程 sp_dbcmptlevel 的信息,请参见帮助。

这个是因为:对升级到 SQL Server 2005 或更高版本的数据库使用 PIVOT 和 UNPIVOT 时,必须将数据库的兼容级别设置为 90 或更高。有关如何设置数据库兼容级别的信息,请参阅 sp_dbcmptlevel (Transact-SQL)。 例如,只需在执行上面脚本前加上 EXEC sp_dbcmptlevel Test, 90; 就OK了, Test 是所在数据库的名称。
分享到:
评论

相关推荐

    DB2 SQL 实现行转列,列转行

    DB2 SQL 通过函数(CONCAT/POSSTR/LOCATE)实现行转列,列转行 可以按照标点把多列转换为一行,多行转换为一列

    SqlServer行转列

    在数据库操作中,行转列(Pivot)是一种将数据表中的行数据转换为列数据的技术。这种技术通常用于改变数据的结构,使得原始数据更适合进一步的数据分析或报告需求。 #### 知识点二:为什么要进行行转列? 1. **...

    将SQL数据表的一列转换为一行.docx

    在 MySQL 中,可以使用以下方法来将 SQL 数据表的一列转换为一行。 知识点1:使用存储过程实现数据转换 在 MySQL 中,可以使用存储过程来实现数据转换。存储过程是一种预先编译好的 SQL 语句集合,可以重复使用以...

    sql动态行转列 存储过程

    在SQL数据库操作中,"行转列"是一种常见的数据转换需求,它将表格中的多行数据转换为单列显示,通常用于数据汇总和分析。在本案例中,我们主要探讨如何使用SQL语句,尤其是存储过程,来实现动态的行转列功能。这在...

    Sql,oracle数据表行转列问题

    本文将详细讲解SQL行转列问题的解决方案,并提供了一个具体的实例来帮助读者更好地理解该问题。 问题描述 假设我们有一个学生成绩表tb,包含姓名、课程和分数三个字段。我们想将该表转换为一个新的表格,其中每一...

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

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

    SQL 行转列+动态获取列名

    SQL 行转列+动态获取列名 通用的动态获取列名

    SQL Server行转列使用

    T-SQL(Transact-SQL)是微软SQL Server所使用的扩展SQL语言,它提供了丰富的数据处理功能,包括行转列。在SQL Server中,有两种主要的方法可以实现这一转换: 1. 使用CASE语句: CASE语句是SQL中一个非常强大的...

    SQL行转列参考代码(sqlserver)

    在SQL Server中,"行转列"是一种常见的数据操作,它可以帮助我们把表格中的多行数据转换成一列,或者将某一列的数据转换为多列显示。这种技术在数据分析、报表制作以及信息展示中非常实用。本文将详细介绍SQL Server...

    Sql语句实现表的行列转换,行转列,列转行

    ### SQL语句实现表的行列转换,行转列,列转行 在处理数据库时,我们经常需要对数据进行各种变换以适应不同的分析需求。其中,“行列转换”就是一种非常实用的功能,它可以帮助我们将表中的行数据转换为列数据,...

    sql行转列解决方案.

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

    SQL行转列显示

    这种转换技术被称为“行转列”或“透视”(Pivot),而在SQL语言中实现这一功能,最常用的方法便是利用PIVOT函数。本文将深入探讨如何使用SQL中的PIVOT函数将表格数据由行格式转换为列格式,并通过具体案例进行详细...

    SQL中如何实现行转列.rar

    在SQL(结构化查询语言)中,行转列是一种常见的数据转换操作,它将数据库表中的多行数据转换为单列或多列显示。这在数据分析、报表制作或数据展示时非常有用。本教程将深入探讨如何在SQL中实现这一功能。 首先,...

    sql利用union all行转列

    本文主要介绍一种利用SQL语句中的`UNION ALL`来实现“行转列”的方法,并通过具体的示例代码进行详细解释。 #### 基本概念理解 1. **UNION ALL**:在SQL中,`UNION`用于合并两个或多个`SELECT`语句的结果集,但会...

    SQL语句将行转换成列

    sql语句将行转换成列 declare @sql varchar(8000) set @sql = 'select 物料代码' select @sql = @sql + ',sum(case 地区 when '''+地区+''' then 数量 end) ['+地区+']' + ',sum(case 地区 when '''+地区+'''...

    SQL---行转列 详细描述

    在SQL Server 2000中,由于缺乏直接支持行转列的内置函数或语句,通常需要通过动态SQL来实现。具体步骤如下: 1. **构建动态SQL语句**:首先,需要查询出所有需要被转换为列的值,并基于这些值构造动态SQL。 2. **...

    sql行转列动态与静态

    根据题目提供的信息,“sql行转列动态与静态”这一主题介绍了三种实现行转列的方法:静态方式、动态方式以及动态生成列的方式。接下来,我们将详细介绍这三种方法及其应用场景。 ### 一、静态方式 静态方式是最...

    sql多行转列

    主要是关于sqlserver的多行转列的问题,这是我经过个人测试的语句。

Global site tag (gtag.js) - Google Analytics