SQL 行转列

摘要:
行转列,列转行是我们在开发过程中经常碰到的问题。聚合函数SUM表示你需要怎样处理转换后的列的值,是总和,还是平均还是min,max等等。
行转列,列转行是我们在开发过程中经常碰到的问题。
1、行转列一般通过CASE WHEN 语句来实现
2、也可以通过 SQL SERVER 2005 新增的运算符PIVOT来实现。
用传统的方法,比较好理解。层次清晰,而且比较习惯。
但是PIVOT 、UNPIVOT提供的语法比一系列复杂的SELECT...CASE 语句中所指定的语法更简单、更具可读性。下面我们通过几个简单的例子来介绍一下列转行、行转列问题。

一、行转列

我们首先先通过一个老生常谈的例子,学生成绩表(下面简化了些)来形象了解下行转列

CREATE  TABLE [StudentScores]
(
   [UserName]         NVARCHAR(20),        --学生姓名
    [Subject]          NVARCHAR(30),        --科目
    [Score]            FLOAT,               --成绩
)

插入数据

SQL 行转列第1张SQL 行转列第2张
INSERT INTO [StudentScores] SELECT 'Nick', '语文', 80
INSERT INTO [StudentScores] SELECT 'Nick', '数学', 90
INSERT INTO [StudentScores] SELECT 'Nick', '英语', 70
INSERT INTO [StudentScores] SELECT 'Nick', '生物', 85
INSERT INTO [StudentScores] SELECT 'Kent', '语文', 80
INSERT INTO [StudentScores] SELECT 'Kent', '数学', 90
INSERT INTO [StudentScores] SELECT 'Kent', '英语', 70
INSERT INTO [StudentScores] SELECT 'Kent', '生物', 85
View Code

如果我想知道每位学生的每科成绩,而且每个学生的全部成绩排成一行,这样方便我查看、统计,导出数据

1、case when 方式

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 dbo.[StudentScores]
GROUP BY UserName
查询结果如图所示,这样我们就能很清楚的了解每位学生所有的成绩了

SQL 行转列第3张

2、PIVOT方式

SELECT * FROM [StudentScores] /*数据源*/
ASP
PIVOT 
(
    SUM(Score/*行转列后 列的值*/) FOR
    p.Subject/*需要行转列的列*/ IN ([语文],[数学],[英语],[生物]/*列的值*/)
) AS T

另举一例做解释:

SELECT [星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]
--这里是PIVOT第三步(选择行转列后的结果集的列)这里可以用“*”表示选择所有列,也可以只选择某些列(也就是某些天),通过TBL来定义列的别名
FROMWEEK_INCOME
 --这里是PIVOT第二步骤(准备原始的查询结果,因为PIVOT是对一个原始的查询结果集进行转换操作,所以先查询一个结果集出来)这里可以是一个select子查询,
 --但为子查询时候要指定别名,否则语法错误

PIVOT
(
    SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])
--这里是PIVOT第一步骤,也是核心的地方,进行行转列操作。聚合函数SUM表示你需要怎样处理转换后的列的值,是总和(sum),还是平均(avg)还是min,max等等。
--例如如果week_income表中有两条数据并且其week都是“星期一”,其中一条的income是1000,另一条income是500,那么在这里使用sum,行转列后“星期一”这个列的值当然是1500了。
--后面的for [week] in([星期一],[星期二]...)中 for [week]就是说将week列的值分别转换成一个个列,也就是“以值变列”。
--但是需要转换成列的值有可能有很多,我们只想取其中几个值转换成列,那么怎样取呢?就是在in里面了,比如我此刻只想看工作日的收入,在in里面就只写“星期一”至“星期五”
--(注意,in里面是原来week列的值,"以值变列")。总的来说,SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])这句的意思直译出来,
--就是说:将列[week]值为"星期一","星期二","星期三","星期四","星期五","星期六","星期日"分别转换成列,这些列的值取income的总和。

)TBL
--别名一定要写

二、列转行

1、测试数据准备

SQL 行转列第1张SQL 行转列第5张
CREATE TABLEProgrectDetail
(
    ProgrectName         NVARCHAR(20), --工程名称
    OverseaSupply        INT,          --海外供应商供给数量
    NativeSupply         INT,          --国内供应商供给数量
    SouthSupply          INT,          --南方供应商供给数量
    NorthSupply          INT           --北方供应商供给数量
)
INSERT INTOProgrectDetail
SELECT 'A', 100, 200, 50, 50
UNION ALL
SELECT 'B', 200, 300, 150, 150
UNION ALL
SELECT 'C', 159, 400, 20, 320
UNION ALL
View Code

SQL 行转列第6张

sql语句:

SELECTP.ProgrectName,P.Supplier,P.SupplyNum
FROM
(
    SELECTProgrectName, OverseaSupply, NativeSupply,
           SouthSupply, NorthSupply
     FROMProgrectDetail
)T
UNPIVOT 
(
    SupplyNum FOR Supplier IN
    (OverseaSupply, NativeSupply, SouthSupply, NorthSupply )
) P

结果:

SQL 行转列第7张

免责声明:文章转载自《SQL 行转列》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Mac-Pycharm中的Terminal(zsh)的python版本和终端python版本不同移动前端—H5实现图片先压缩再上传下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

二十四、Mysql读写分离之Atlas

一、Atlas介绍 Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了大量bug,添加了很多功能特性。目前该项目在360公司内部得到了广泛应用,很多MySQL业务已经接入了Atlas平台,每天承载的读写请求数达几十亿条...

查看sql server数据库连接情况

1.通过系统的“性能”来查看:开始->管理工具->性能(或者是运行里面输入 mmc)然后通过添加计数器添加 SQL 的常用统计(MSSQL General Statistics) 然后在下面列出的项目里面选择 用户连接(User Connection) 就可以时时查询到sql server数据库连接数了。 2.通过系统表来查询: 查询数据库当前...

oracle非归档模式下的冷备份和恢复

查看归档的相关信息 SQL> archive log list数据库日志模式 非存档模式自动存档 禁用存档终点 USE_DB_RECOVERY_FILE_DEST最早的联机日志序列 72当前日志序列 74 备份中常用的术语解释: 冷备份(脱机备份): 数据库处于关闭状态下所做的物理拷贝。数据库处于非归档模式下只能使用这种方法备份。 数据库全备份:备份...

SQL serve 数据库--视图、事物、分离附加、备份还原

视图是数据库中的一种虚拟表,与真实的表一样,视图包含一系列带有名称的行和列数据。行和列数据用来自定义视图的查询所引用的表,并且在引用视图时动态生成。 视图只能用来查询,不能增删改;不允许出现重复列 1. 视图的概念 视图是从一个或者多个表中导出的,其行为与表相似,但视图是一个虚拟表。视图可以在已经存在的视图的基础上定义。在视图上用户可以使用SELECT语...

Spring Boot整合Mybatis配置详解

首先,你得有个Spring Boot项目。 平时开发常用的repository包在mybatis里被替换成了mapper。 配置: 1.引入依赖: <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-s...

SQLServer查看分区表详细信息

SQL查看分区内记录个数,常规方法需要知道分区函数然后再显示,网上看到一个一句话显示的方法 select convert(varchar(50), ps.name ) aspartition_scheme, p.partition_number, convert(varchar(10), ds2.name ) asfilegroup, con...