SQL SERVER PIVOT 行转列、列传行

在数据库操作中,有些时候我们遇到需要实现“行转列”的需求,例如一下的表为某店铺的一周收入情况表:

WEEK_INCOME(WEEK VARCHAR(10),INCOME DECIMAL)

我们先插入一些模拟数据:

复制代码
INSERT INTO WEEK_INCOME 
SELECT '星期一',1000
UNION ALL
SELECT '星期二',2000
UNION ALL
SELECT '星期三',3000
UNION ALL
SELECT '星期四',4000
UNION ALL
SELECT '星期五',5000
UNION ALL
SELECT '星期六',6000
UNION ALL
SELECT '星期日',7000
复制代码

 

一般我们最经常使用的查询是查询一周中每天或某几天的收入,例如查询周一至周日全部的收入:

SELECT WEEK,INCOME FROM WEEK_INCOME

得到如下的查询结果集:

WEEK           INCOME
星期一           1000
星期二           2000
星期三           3000
星期四           4000
星期五           5000
星期六           6000
星期日           7000

 

但是在一些情况下(往往是某些报表中),我们希望在一行中显示周一至周日的收入,这时候查询结果集应该是这样的:

星期一   星期二   星期三   星期四   星期五   星期六   星期日
1000     2000     3000     4000     5000     6000     7000

这种情况下,SQL查询语句可以这样写:

复制代码
SELECT  
SUM(CASE WEEK WHEN '星期一' THEN INCOME END) AS [星期一],
SUM(CASE WEEK WHEN '星期二' THEN INCOME END) AS [星期二],
SUM(CASE WEEK WHEN '星期三' THEN INCOME END) AS [星期三],
SUM(CASE WEEK WHEN '星期四' THEN INCOME END) AS [星期四],
SUM(CASE WEEK WHEN '星期五' THEN INCOME END) AS [星期五],
SUM(CASE WEEK WHEN '星期六' THEN INCOME END) AS [星期六],
SUM(CASE WEEK WHEN '星期日' THEN INCOME END) AS [星期日]
FROM WEEK_INCOME
复制代码

但是,在SQL SERVER 2005中提供了更为简便的方法,这就是"PIVOT"关系运算符。(相反的“列转行”是UNPIVOT),以下是使用PIVOT实现“行转列”的SQL语句

SELECT [星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]
FROM WEEK_INCOME
PIVOT
(SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])
)TBL

 

 

请参考MSDN中关于PIVOT的用法:

http://technet.microsoft.com/zh-cn/library/ms177410(v=sql.105).aspx

 

但是MSDN上的描述太过于规范严肃,我看了半天还没弄清楚怎样使用PIVOT,搞不清楚PIVOT里面的语法的含义。于是又google了很多资料,以及通过上面提到的WEEK_INCOME表例子作了试验,最终搞清楚了其用法。在网上有篇博文解释的很好:T-SQL PIVOT語法剖析與實戰,基本上我要写的就是参照该博文,再加上自己一点个人理解。

要理解PIVOT语法,就是要清楚微软为什么这样设计PIVOT,但我相信是现实需求催生设计思路,所以归根到底我们还是要弄清楚什么是“行转列”:

正常情况下的查询结果是这样:

星期一           1000
星期二           2000
星期三           3000
星期四           4000
星期五           5000
星期六           6000
星期日           7000

行转列后是这样:

星期一   星期二   星期三   星期四   星期五   星期六   星期日
1000    2000    3000    4000    5000    6000    7000

也就是说,行转列后,原来的某个列的值变做了列名,在这里就是原来WEEK列的值“星期一”,"星期二"..."星期日"边做了列名,而我们需要做的另一个工作就是计算这些列的值(这里的“计算”其实就是PIVOT里面的聚合函数(sum,avg等))

现在结合注释来分析一下PIVOT语法(在这之前最好看看我上面提到博文:T-SQL PIVOT語法剖析與實戰,里面说到的PIVOT语法的三个步骤挺重要):

复制代码
SELECT [星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]--这里是PIVOT第三步(选择行转列后的结果集的列)这里可以用“*”表示选择所有列,也可以只选择某些列(也就是某些天)
FROM WEEK_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--别名一定要写
复制代码

 

以上是我对PIVOT的理解,我尽所能表达出来。不过话说回来,个人的理解的方式也不同,就如我开始看了很多篇博文,都没有搞清楚PIVOT用法。结果还是硬的通过例子和别人的博文再加上思考才弄懂了,所以如果各位看了本篇之后仍不能理解,那很正常,配合例子再加上自己思考,慢慢的定能理解。

转载于:https://www.cnblogs.com/ajunForNet/p/4446662.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/472075.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql cluster 查看数据库表名称_MySQL Cluster如何创建磁盘表方法解读

MySQL Cluster采用一系列的Disk Data objects来实现磁盘表;接下来为您详细介绍一、概念MySQL Cluster采用一系列的Disk Data objects来实现磁盘表。Tablespaces:作用是作为其他Disk Data objects的容器。Undo log files:存储事务进行回滚需要的信息&…

(运算符) 运算符

& 运算符既可作为一元运算符也可作为二元运算符。 备注 一元 & 运算符返回操作数的地址(要求 unsafe 上下文)。 为整型和 bool 类型预定义了二进制 & 运算符。 对于整型,& 计算操作数的逻辑按位“与”。 对于 bool 操作数&am…

LeetCode 1903. 字符串中的最大奇数

文章目录1. 题目2. 解题1. 题目 给你一个字符串 num ,表示一个大整数。 请你在字符串 num 的所有 非空子字符串 中找出 值最大的奇数 ,并以字符串形式返回。如果不存在奇数,则返回一个空字符串 “” 。 子字符串 是字符串中的一个连续的字符…

mysql分页插件springboot_SpringBoot--使用Mybatis分页插件

1、导入分页插件包和jpa包org.springframework.bootspring-boot-starter-data-jpacom.github.pagehelperpagehelper-spring-boot-starter1.2.52、增加分页配置# 主键自增回写方法,默认值MYSQL,详细说明请看文档mapper:identity: MYSQL# 设置 insert 和 update 中,是…

LeetCode 1904. 你完成的完整对局数

文章目录1. 题目2. 解题1. 题目 一款新的在线电子游戏在近期发布,在该电子游戏中,以 刻钟 为周期规划若干时长为 15 分钟 的游戏对局。 这意味着,在 HH:00、HH:15、HH:30 和 HH:45 ,将会开始一个新的对局,其中 HH 用一…

LeetCode 1905. 统计子岛屿(BFS)

文章目录1. 题目2. 解题1. 题目 给你两个 m x n 的二进制矩阵 grid1 和 grid2 ,它们只包含 0 (表示水域)和 1 (表示陆地)。 一个 岛屿 是由 四个方向 (水平或者竖直)上相邻的 1 组成的区域。 任…

vue是什么软件_Angular vs React vs Vue:2020年的最佳选择是什么?

在2020年,想象没有HTML,CSS和Javascript的Web开发是不切实际的。 Javascript是Web应用程序前端开发的灵魂。 如果您登陆此页面,那么我认为您在Java语言和Java编程语言的不同框架和库之间感到困惑。企业和软件开发人员最常见的一些查询是&…

LeetCode 1910. 删除一个字符串中所有出现的给定子字符串

文章目录1. 题目2. 解题1. 题目 给你两个字符串 s 和 part ,请你对 s 反复执行以下操作直到 所有 子字符串 part 都被删除: 找到 s 中 最左边 的子字符串 part ,并将它从 s 中删除。 请你返回从 s 中删除所有 part 子字符串以后得到的剩余…

tcp长连接和短连接的区别_TCP --- 连接

一个TCP连接由4个元组组成:2个ip地址和2个端口号tcp三次握手为什么是三次握手解决历史连接问题通过三次握手才能阻止重复历史连接的初始化通过三次握手,才能对通讯双方的初始序号初始化如果只有2次握手,发送方一旦发送创建连接的请求就无法撤…

LeetCode 1911. 最大子序列交替和(动态规划)

文章目录1. 题目2. 解题1. 题目 一个下标从 0 开始的数组的 交替和 定义为 偶数 下标处元素之 和 减去 奇数 下标处元素之 和 。 比方说,数组 [4,2,5,3] 的交替和为 (4 5) - (2 3) 4 。 给你一个数组 nums ,请你返回 nums 中任意子序列的 最大交替和…

LeetCode 1912. 设计电影租借系统(map+set)

文章目录1. 题目2. 解题1. 题目 你有一个电影租借公司和 n 个电影商店。 你想要实现一个电影租借系统,它支持查询、预订和返还电影的操作。 同时系统还能生成一份当前被借出电影的报告。 所有电影用二维整数数组 entries 表示,其中 entries[i] [shopi…

python第一周心得_python第一周心得-Go语言中文社区

Python 简介Python 作为一个近年备受好评的语言,它的一些优点让人无法忽视。Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。它的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号&am…

使用预训练模型进行句对分类(Paddle、PyTorch)

文章目录1. Paddle2. PyTorch3. 提交结果分别使用两种框架,加载预训练模型,对句对进行分类 数据下载:千言数据集:文本相似度 1. Paddle 可以使用 paddlenlp 直接加载预训练模型,比较方便 # %% # 比赛地址 # https…

mysql1033错误存储引擎_MySQL Innodb存储引擎因为缓存配置出现的错误

引用100920 10:50:21 mysqld_safe Starting mysqld daemon with databases from /byread/dataInnoDB: The InnoDB memory heap is disabledInnoDB: Mutexes and rw_locks use GCC atomic builtinsInnoDB: mmap(11010048000 bytes) failed; errno 12InnoDB: Fatal error: cannot…

LeetCode 1913. 两个数对之间的最大乘积差

文章目录1. 题目2. 解题1. 题目 两个数对 (a, b) 和 (c, d) 之间的 乘积差 定义为 (a * b) - (c * d) 。 例如,(5, 6) 和 (2, 7) 之间的乘积差是 (5 * 6) - (2 * 7) 16 。 给你一个整数数组 nums ,选出四个 不同的 下标 w、x、y 和 z ,使数…

PHP和MySQL开发WordPress_wordpress是什么开发的

wordpress是什么开发的?WordPress是一个以PHP和MySQL为平台的自由开源的博客软件和内容管理系统。WordPress具有插件架构和模板系统。截至2018年4月,排名前1000万的网站超过30.6%使用WordPress。WordPress是最受欢迎的网站内容管理系统。WordPress是目前…

LeetCode 1920. 基于排列构建数组

文章目录1. 题目2. 解题1. 题目 给你一个 从 0 开始的排列 nums&#xff08;下标也从 0 开始&#xff09;。 请你构建一个 同样长度 的数组 ans &#xff0c;其中&#xff0c;对于每个 i&#xff08;0 < i < nums.length&#xff09;&#xff0c;都满足 ans[i] nums[nu…

LeetCode 1922. 统计好数字的数目(快速幂)

文章目录1. 题目2. 解题1. 题目 我们称一个数字字符串是 好数字 当它满足&#xff08;下标从 0 开始&#xff09;偶数 下标处的数字为 偶数 且 奇数 下标处的数字为 质数 &#xff08;2&#xff0c;3&#xff0c;5 或 7&#xff09;。 比方说&#xff0c;“2582” 是好数字&a…

LeetCode 1933. 判断字符串是否可分解为值均等的子串

文章目录1. 题目2. 解题1. 题目 一个字符串的所有字符都是一样的&#xff0c;被称作等值字符串。 举例&#xff0c;"1111" 和 "33" 就是等值字符串。 相比之下&#xff0c;"123"就不是等值字符串。 规则&#xff1a;给出一个数字字符串s&…

LeetCode 1921. 消灭怪物的最大数量(排序)

文章目录1. 题目2. 解题1. 题目 你正在玩一款电子游戏&#xff0c;在游戏中你需要保护城市免受怪物侵袭。 给你一个 下标从 0 开始 且长度为 n 的整数数组 dist &#xff0c;其中 dist[i] 是第 i 个怪物与城市的 初始距离&#xff08;单位&#xff1a;米&#xff09;。 怪物以…