在平常的工作中或者面试中,我们可能有遇到过数据库的纵横表的转换问题。今天我们就来讨论下。

1.创建表

  首先我们来创建一张表。

sql语句:

  1. --1. 创建数据表
  2. if OBJECT_ID('Score') is not null drop table Score
  3.  
  4. create table Score
  5. (
  6. 姓名 nvarchar(128),
  7. 课程 nvarchar(128),
  8. 分数 int
  9. )
  10.  
  11. insert into Score values('张三','语文',98)
  12. insert into Score values('张三','数学',89)
  13. insert into Score values('张三','物理',78)
  14. insert into Score values('李四','语文',79)
  15. insert into Score values('李四','数学',88)
  16. insert into Score values('李四','物理',100)
  17.  
  18. select * from Score

执行结果:

2. 传统的纵横表转换

2.1 纵表转横表

先看看我们要转成的横表张什么样子:

既然这个表只有两列,那么可以根据姓名进行分组。先把姓名拼凑出来,后面的分数我们再想办法。

sql:

  1. select t.姓名 2 from Score as t 3 group by t.姓名

结果:

分析:

  1. 我们先拿到语文这个科目的分数。既然我们用到了group by 语句,这里肯定要用聚合函数来求分数。
  2. 而且我们只需要语文这一科的成绩,分组出来的 一共有 3列 ,分别是 语文、数学、物理  。  那么就需要判断科目来取分数。

这里符合我们需求的 case 语句就登场了。他和c#中switch-case 作用一样。

sql case 语句语法:

  1. case 字段
  2. when 1 then 结果
  3. when 2 then 结果2
  4. ...
  5. else 默认结果
  6. end

求语文的分数就简单了:

  1. select t.姓名,
  2. SUM(case t.课程 when '语文' then t.分数 else 0 end) as 语文
  3. from Score as t
  4. group by t.姓名

结果:

既然语文的分数取到了,其他科目改变下条件就可以了。

完整的sql:

  1. select t.姓名,
  2. SUM(case t.课程 when '语文' then t.分数 else 0 end) as 语文,
  3. SUM(case t.课程 when '数学' then t.分数 else 0 end) as 数学,
  4. SUM(case t.课程 when '物理' then t.分数 else 0 end) as 物理
  5. from Score as t
  6. group by t.姓名

OK,到这儿,我们传统方式的纵表转横表就大功告成了。

2.2 横表转纵表

那么我们可以把转换过来的横表再转换回去吗?

我们先把刚刚转好的表,插入一个新表ScoreHb 中。

  1. -- 转换的表插入新表
  2. select t.姓名,
  3. SUM(case t.课程 when '语文' then t.分数 else 0 end) as 语文,
  4. SUM(case t.课程 when '数学' then t.分数 else 0 end) as 数学,
  5. SUM(case t.课程 when '物理' then t.分数 else 0 end) as 物理
  6. into ScoreHb
  7. from Score as t
  8. group by t.姓名

这时ScoreHb 就是我们刚转换好的横表,我们再想办法把他转回来。

怎么转呢? 一步步来。我们也先把张三和李四的语文成绩查出来。

sql:

  1. --张三李四语文的分数
  2. select t.姓名,
  3. '语文' as 课程,
  4. t.语文 as 分数
  5. from ScoreHb as t

结果:

还有两科的数据怎么办呢? 很简单,我们一个个都查出来,然后用 union all 把他们组合为一张表就可以了。

sql:

  1. -- union all链接3个科目
  2. select t.姓名,
  3. '语文' as 课程,
  4. t.语文 as 分数
  5. from ScoreHb as t
  6. union all
  7. select t.姓名,
  8. '数学' as 课程,
  9. t.数学 as 分数
  10. from ScoreHb as t
  11. union all
  12. select t.姓名,
  13. '物理' as 课程,
  14. t.物理 as 分数
  15. from ScoreHb as t
  16. order by t.姓名 desc

结果:

这样,我们就把表又变回去了。

但是大家有没有觉得很麻烦呢?别急,我们有更简单的办法。下面为大家介绍pivot关系运算符。

3. 用pivot和unpivot运算符进行转换

  pivot是sql server 2005 提供的运算符,所以只要数据库在05版本以上的都可以使用。主要用于行和列的转换。

3.1 pivot纵表转横表

sql:

  1. select
  2. t2.姓名,
  3. t2.数学,
  4. t2.物理,
  5. t2.语文
  6. from Score as t1
  7. pivot (sum(分数) for 课程 in(数学,语文,物理)) as t2

结果:

是不是代码简洁多了。

pivot将原来表中 课程字段中的 数据行 数学,语文,物理 转换为列,并用sum取对应列的值。

我们只需要记住它的用法就可以了。

3.2 unpivot 横表转纵表

既然有privot可以纵表转横表。那么有没有运算符帮我们转回来呢?

答案是肯定的,他就是unpivot

sql:

  1. select
  2. *
  3. from
  4. ScoreHb
  5. unpivot (分数 for 课程 in (语文,数学,物理)) as t4

结果:

 unpivot 将 语文,数学,物理 列转为行,分数为新的一列存放对应的值。

是不是比我们之前一个个表查询拼接,方便了很多。

sql server 纵横表的转换的更多相关文章

  1. sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)

    sql server 关于表中只增标识问题   由于我们系统时间用的过长,数据量大,设计是采用自增ID 我们插入数据的时候把ID也写进去,我们可以采用 关闭和开启自增标识 没有关闭的时候 ,提示一下错 ...

  2. SQL Server创建表超出行最大限制解决方法

    问题的现象在创建表A的时候,出现“信息 511,级别 16,状态 1,第 5 行  无法创建大小为 的行,该值大于允许的最大值 8060.”的信息提示.很奇怪,网上查了一下,是因为要插入表的数据类型的 ...

  3. SQL Server日期时间格式转换字符串详解 (详询请加qq:2085920154)

    在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...

  4. SQL Server日期时间格式转换字符串

    在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...

  5. 千万级SQL Server数据库表分区的实现

    千万级SQL Server数据库表分区的实现 2010-09-10 13:37 佚名 数据库 字号:T | T 一般在千万级的数据压力下,分区是一种比较好的提升性能方法.本文将介绍SQL Server ...

  6. Azure 意外重启, 丢失sql server master表和 filezilla

    突然发现今晚网站打不开了,提示连不上数据库. ftp也连不上了. 远程连上Azure 发现机器意外重启, 丢失sql server master表和 filezilla 要重新安装. 又耗费我几个小时 ...

  7. SQL Server 系统表简介

    SQL Server 系统表简介 系统目录是由描述SQL Server 系统的数据库.基表.视图和索引等对象的结构的系统表组成.SQL Server 经常访问系统目录,检索系统正常运行所需的必要信息. ...

  8. [SQL]SQL Server数据表的基础知识与增查删改

    SQL Server数据表的基础知识与增查删改 由张晨辉(学生) 于19天 前发表 | 阅读94次 一.常用数据类型 .整型:bigint.int.smallint.tinyint .小数:decim ...

  9. SQL Server 锁表、查询被锁表、解锁相关语句

    SQL Server 锁表.查询被锁表.解锁相关语句,供参考. --锁表(其它事务不能读.更新.删除) BEGIN TRAN SELECT * FROM <表名> WITH(TABLOCK ...

随机推荐

  1. QuickSort again

    I wrote a blog about Quick Sort before. Let's talk more about it. If you don't think that the implem ...

  2. 利用 :before 特性实现图片按比例显示

    好吧,想不到自称布局小沙弥的我会被图片按比例显示给尴尬到. 设计师跟我说,这里的图要按 750x330 的,好吧,但这图是屏宽呀,屏幕宽度会变化的,那高度也会不定咯, 要么裁图片(工作量大),要么给定 ...

  3. MongoDB命令语法小用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using MongoDB; ...

  4. 自己的第一个MapReduce程序

    数据源:来自互联网招聘hadoop岗位的薪资数据,其中几行示例数据如下: 美团 3-5年经验 15-30k 北京 [够牛就来]hadoop高级工程... 北信源 3-5年经验 15-20k 北京 Ja ...

  5. 【转】Android中的IOC框架,完全注解方式就可以进行UI绑定和事件绑定

    转载请注明出处:http://blog.csdn.net/blog_wang/article/details/38468547 相信很多使用过Afinal和Xutils的朋友会发现框架中自带View控 ...

  6. BASE64Encoded() 方法报错说方法未定义

    代码: String enParams = new BASE64Encoder().encode(strParams.getBytes()); 出错,显示方法未定义 解决方法:项目右键——>pr ...

  7. Android 手机上获取手机当前上网IP地址

      [转] 原文              Android 手机上获取手机当前上网IP地址                (手机网关给手机号分配的IP) 每个手机上网通过移动网关的时候,网关都会给该手 ...

  8. CreateThread创建线程传递结构体参数

    #include "stdafx.h" #include <stdio.h> #include <windows.h> #include <stdli ...

  9. 由于ptrace.h文件导致的内核编译出错的解决方法

    arch/x86/kernel/ptrace.c:1472:17: error: conflicting types for 'syscall_trace_enter'  In file includ ...

  10. 最全面的linux信号量解析

    信号量 一.什么是信号量 信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程) 所拥有. 信号量的值为正的时候,说明它空闲.所测试的线程可以锁定而使用它.若为0,说明 它被占用, ...