hive 行转列和列转行的方法_面试常考!SQL行转列和列转行

关注上方“数据挖掘工程师”,选择星标,关键时间,第一时间送达!2ae503772f630a3306d4323bef9e8e95.png行转列,列转行是我们在开发过程中经常碰到的问题。行转列一般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER 的运算符PIVOT来实现。用传统的方法,比较好理解。层次清晰,而且比较习惯。但是PIVOT 、UNPIVOT提供的语法比一系列复杂的SELECT…CASE 语句中所指定的语法更简单、更具可读性。下面我们通过几个简单的例子来介绍一下列转行、行转列问题。我们首先先通过一个老生常谈的例子,学生成绩表(下面简化了些)来形象了解下行转列CREATE  TABLE [StudentScores]
(
  [UserName]         NVARCHAR(20),        --学生姓名
   [Subject]          NVARCHAR(30),        --科目
   [Score]            FLOAT,               --成绩
)INSERT INTO [StudentScores] SELECT 'Nick', '语文', 80INSERT INTO [StudentScores] SELECT 'Nick', '数学', 90INSERT INTO [StudentScores] SELECT 'Nick', '英语', 70INSERT INTO [StudentScores] SELECT 'Nick', '生物', 85INSERT INTO [StudentScores] SELECT 'Kent', '语文', 80INSERT INTO [StudentScores] SELECT 'Kent', '数学', 90INSERT INTO [StudentScores] SELECT 'Kent', '英语', 70INSERT INTO [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 dbo.[StudentScores]GROUP BY UserName查询结果如图所示,这样我们就能很清楚的了解每位学生所有的成绩了bab5ea7c0b6eae44cc38952d36086b3a.png接下来我们来看看第二个小列子。有一个游戏玩家充值表(仅仅为了说明,举的一个小例子),CREATE TABLE [Inpours]
(
  [ID]                INT IDENTITY(1,1),
  [UserName]          NVARCHAR(20),  --游戏玩家
   [CreateTime]        DATETIME,      --充值时间
   [PayType]           NVARCHAR(20),  --充值类型
   [Money]             DECIMAL,       --充值金额
   [IsSuccess]         BIT,           --是否成功 1表示成功, 0表示失败CONSTRAINT [PK_Inpours_ID] PRIMARY KEY(ID)
)INSERT INTO Inpours SELECT '张三', '2010-05-01', '支付宝', 50, 1INSERT INTO Inpours SELECT '张三', '2010-06-14', '支付宝', 50, 1INSERT INTO Inpours SELECT '张三', '2010-06-14', '手机短信', 100, 1INSERT INTO Inpours SELECT '李四', '2010-06-14', '手机短信', 100, 1INSERT INTO Inpours SELECT '李四', '2010-07-14', '支付宝', 100, 1INSERT INTO Inpours SELECT '王五', '2010-07-14', '工商银行卡', 100, 1INSERT INTO Inpours SELECT '赵六', '2010-07-14', '建设银行卡', 100, 1下面来了一个统计数据的需求,要求按日期、支付方式来统计充值金额信息。这也是一个典型的行转列的例子。我们可以通过下面的脚本来达到目的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 InpoursGROUP BY CreateTime, PayType如图所示,我们这样只是得到了这样的输出结果,还需进一步处理,才能得到想要的结果31ced472603d6a9e15c72f5d257e5592.pngSELECT
      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 InpoursGROUP BY CreateTime, PayType
) TGROUP BY CreateTime其实行转列,关键是要理清逻辑,而且对分组(Group by)概念比较清晰。上面两个列子基本上就是行转列的类型了。但是有个问题来了,上面是我为了说明弄的一个简单列子。实际中,可能支付方式特别多,而且逻辑也复杂很多,可能涉及汇率、手续费等等(曾经做个这样一个),如果支付方式特别多,我们的CASE WHEN 会弄出一大堆,确实比较恼火,而且新增一种支付方式,我们还得修改脚本如果把上面的脚本用动态SQL改写一下,我们就能轻松解决这个问题DECLARE @cmdText    VARCHAR(8000);DECLARE @tmpSql        VARCHAR(8000);SET @cmdText = 'SELECT CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime,' + CHAR(10);SELECT @cmdText = @cmdText + ' CASE PayType WHEN ''' +
PayType + ''' THEN SUM(Money) ELSE 0 END AS ''' + PayType
      + ''',' + CHAR(10)  FROM (SELECT DISTINCT PayType FROM Inpours ) TSET @cmdText = LEFT(@cmdText, LEN(@cmdText) -2) --注意这里,如果没有加CHAR(10) 则用LEFT(@cmdText, LEN(@cmdText) -1)SET @cmdText = @cmdText + ' FROM Inpours    
   GROUP BY CreateTime, PayType ';SET @tmpSql ='SELECT CreateTime,' + CHAR(10);SELECT @tmpSql = @tmpSql + ' ISNULL(SUM(' + PayType  + '), 0) AS ''' +
PayType  + ''','  + CHAR(10)FROM  (SELECT DISTINCT PayType FROM Inpours ) TSET @tmpSql = LEFT(@tmpSql, LEN(@tmpSql) -2) + ' FROM (' + CHAR(10);SET @cmdText = @tmpSql + @cmdText + ') T GROUP BY CreateTime ';
PRINT @cmdTextEXECUTE (@cmdText);下面是通过PIVOT来进行行转列的用法,大家可以对比一下,确实要简单、更具可读性SELECT CreateTime, [支付宝] , [手机短信],[工商银行卡] , [建设银行卡]FROM
(SELECT CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime,PayType, MoneyFROM Inpours
) PPIVOT (SUM(Money)FOR PayType IN
           ([支付宝], [手机短信], [工商银行卡], [建设银行卡])
     ) AS TORDER BY CreateTime有时可能会出现这样的错误:
消息 325,级别 15,状态 1,第 9 行‘PIVOT’ 附近有语法错误。您可能需要将当前数据库的兼容级别设置为更高的值,以启用此功能。有关存储过程 sp_dbcmptlevel 的信息,请参见帮助。
这个是因为:对升级到 SQL Server 2005 或更高版本的数据库使用 PIVOT 和 UNPIVOT 时,必须将数据库的兼容级别设置为 90 或更高。有关如何设置数据库兼容级别的信息,请参阅 sp_dbcmptlevel (Transact-SQL)。例如,只需在执行上面脚本前加上 EXEC sp_dbcmptlevel Test, 90; 就OK了, Test 是所在数据库的名称。下面我们来看看列转行,主要是通过UNION ALL ,MAX来实现。假如有下面这么一个表Create Table ProgrectDetail
(
   ProgrectName         NVARCHAR(20), --工程名称
   OverseaSupply        INT,          --海外供应商供给数量
   NativeSupply         INT,          --国内供应商供给数量
   SouthSupply          INT,          --南方供应商供给数量
   NorthSupply          INT           --北方供应商供给数量
)INSERT INTO ProgrectDetailSELECT 'A', 100, 200, 50, 50UNION ALLSELECT 'B', 200, 300, 150, 150UNION ALLSELECT 'C', 159, 400, 20, 320UNION ALLSELECT 'D', 250, 30, 15, 15我们可以通过下面的脚本来实现,查询结果如下图所示SELECT  ProgrectName, 'OverseaSupply' AS Supplier,MAX(OverseaSupply) AS 'SupplyNum'FROM ProgrectDetailGROUP BY ProgrectNameUNION ALLSELECT ProgrectName, 'NativeSupply' AS Supplier,MAX(NativeSupply) AS 'SupplyNum'FROM ProgrectDetailGROUP BY ProgrectNameUNION ALLSELECT ProgrectName, 'SouthSupply' AS Supplier,MAX(SouthSupply) AS 'SupplyNum'FROM ProgrectDetailGROUP BY ProgrectNameUNION ALLSELECT ProgrectName, 'NorthSupply' AS Supplier,MAX(NorthSupply) AS 'SupplyNum' FROM ProgrectDetailGROUP BY ProgrectNameca5658979e233b150d72ab16dc1f9fd9.png用UNPIVOT 实现如下:SELECT ProgrectName,Supplier,SupplyNumFROM  
(SELECT ProgrectName, OverseaSupply, NativeSupply,
          SouthSupply, NorthSupplyFROM ProgrectDetail
)TUNPIVOT  
(
   SupplyNum FOR Supplier IN
   (OverseaSupply, NativeSupply, SouthSupply, NorthSupply )
) P作者:潇湘隐者www.cnblogs.com/kerrycode/archive/2010/07/28/1786547.html特别推荐

Java极客们都在关注「JavaGeek」,专注分享Java技术干货,包括多线程、JVM、Spring Boot、Spring Cloud、Intellij IDEA、Dubbo、Zookeeper、Redis、架构设计、微服务等。

关注并回复「Java学习」获得 1024G Java学习资料5ff284ee68a4b5e44f1c731853bca6eb.png推荐阅读40000字笔记!HiveSQL再不懂来找我!内部泄露版!互联网大厂的薪资和职级一览好文!10年数据分析老司机的深度思考!VS Code、Atom、Sublime Text:谁才是真正的编辑器之王?太强了!这个 Jupyter notebook 离线工具可以用一辈子!经典的SparkSQL/Hive-SQL/MySQL面试-练习题“干货学习,三连

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

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

相关文章

.net core 装了没生效_王者荣耀:辅助装出现惊天bug?辅助光环对自己无效?

大家好,我是老刘备。今天说的这个bug我已经发现许久,从新版本以来就一直在出现,起初我以为是辅助装的光环改动了,但是最近和我的小伙伴开黑之后也遇到这个bug,才发现不是如此。本期我就来带大家一起看看。辅助光环技我…

python sns绘制回归线_Python数分实战:员工流失情况预测

在很久之前,我有写一个Excel数据分析的实战项目,不晓得大家还记不记得,感兴趣的童鞋可以回看:A九姑娘:Excel数分实战:员工流失率分析​zhuanlan.zhihu.com本次的项目数据依旧是这个,但是我们这次…

go var 一个整数_Go语言学习基础-值、变量、常量

Hello world第一个程序是打印经典的“hello world”信息。保存为hello-world.go文件,在命令行中使用go run命令运行程序。若要构建为二进制文件,则使用go build来实现,然后直接执行二进制文件。结果:$ go run hello-world.gohello…

怎么取消自动格式化_iPhone自动扣费怎么取消?App Store、微信、支付宝关闭自动扣费教程...

经常有网友反馈,自己的手机每月会被不知不觉的被扣钱,但又不知道如何关闭,烦恼不已。其实,现在很多视频、音乐、购物等APP都有会员充值功能,其中不少还包含“自动续费”功能,一旦开启会员,今后就…

c# selenium chrome 文件下载_Selenium 框架原理以及环境安装

Selenium 框架原理图片来自转载 蓝色的图Selenium Language Binding就是我们平时使用的编码语言,包括java、python、C#等。可以看到这些语言并没有直接与Browser Drivers进行通信,而是通过了JSON WireProtocol,这就是webdriver协议 &#xff…

怎么打包图片_怎么将许多张照片打包发到邮箱?

怎么将许多张照片打包发到邮箱?所谓的打包,就是需要你把大量照片文件变成一个压缩文件,类似于放到一个文件夹内,也可以理解为把多张纸质照片装订成一个相册,而在装订过程中需要相应工具才能完成。使用压缩包发送文件&a…

dram sram利用 利用_使用量子力学技术的新型超低功耗存储器或将取代DRAM和Flash...

雷锋网按:业界普遍认为未来从数据中将能挖掘出最大的价值,但要挖掘数据的价值除了需要很强的计算能力之外,数据的存储也非常关键。目前,新型存储器也是领先的企业非常关注的一个方向,兰开斯特大学(Lancaster Universit…

mac地址转换_mac电脑格式转化工具

软件下载【软件名称】:Permute【系统支持】:MAC电脑【位数支持】:32位/64位软件下载地址:链接:https://pan.baidu.com/s/1OAEpnvmkQgqd9MMq3Rucow提取码:tgt7注:阿狸提供用户下载的所有内容均来…

电脑怎么打出冒号符号_Mac小技巧:教你如何在Mac电脑打出command?、option?等特殊符号...

很多Mac新用户不知道该如何打出command⌘、option⌥等特殊符号,而网上好多关于打出Mac特殊符号的教程已经过期,或者繁琐看不懂。今天为大家分享一份简单,一看就懂的Mac电脑怎么打出command⌘、option⌥等特殊符号教程。1.我们打开系统偏好设置…

arraylist下标从几开始_漫画:为什么计算机从 0 开始计数,而不是从 1 开始?

作者 | 漫话编程来源 | 漫话编程当我们想要写一个循环体&#xff0c;期望执行10次的时候&#xff0c;我们会使用以下方式&#xff1a;for (int i0; i<10; i){}可以看到&#xff0c;为了保证循环10次&#xff0c;我们定义了一个整数变量从0开始。还有&#xff0c;当我们定义数…

python 爬虫代码_Python 你见过三行代码的爬虫吗

Python 使用Lassie库&#xff0c;仅编写三行代码就能爬取静态页面上的图片和视频。Python实战教程每次讲爬虫的时候都会从“发送请求” 开始讲&#xff0c;讲到解析页面的时候可能大部分读者都会卡住&#xff0c;因为这部分确实需要一点XPATH或者CSS选择器的前置知识。那么有没…

接口传值后不起作用_聊一聊 API 接口测试

知其然亦知其所以然&#xff0c;接口测试没有那么复杂&#xff0c;但也没有那么简单。本文作者&#xff1a;张敏&#xff0c;软件测试工程师&#xff0c;就职于一家容器平台解决方案公司&#xff0c;负责 DevOps 产品的测试。什么是 APIAPI(Application Programming Interface)…

服务器无法在发送 http 标头之后设置内容类型。_python socket编程预知内容

socket&#xff1a;运用IP地址协议端口 标识一个进程我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程&#xff0c; 在本地进程通讯中我们可以使用PID来唯一标示一个进程&#xff0c;但PID只在本地唯一&#xff0c;网络中的两个进程PID冲突几率很大 …

自定义键盘组件_一文读懂!iOS系统组件的设计规范全解

一说到组件&#xff0c;大部分初级设计师和中级设计师的脑海里只会蹦出弹窗、Toast及操作列表等具体的概念&#xff0c;没有一套属于自己的组件分类体系&#xff0c;这样对于视觉设计、交互设计或产品设计的系统学习来说都是不利的。iOS14概念设计iOS官方设计指南在介绍组件时是…

anaconda安装python视频_怎么安装anaconda?

安装 Anaconda步骤&#xff1a; 1、双击下载好的 Anaconda2-5.2.0-Windows-x86_64.exe文件&#xff0c;出现如下界面&#xff0c;点击 Next 即可。2、点击 I Agree &#xff08;我同意&#xff09;3、Install for: Just me还是All Users&#xff0c;假如你的电脑有好几个 Users…

office365 自定义_IT外包观察,足不出户,Office365打造教学新体验?

Office365无疑是当今最高效的集文档处理、联机协同、移动办公、快捷沟通、商业智能为一体的云端生产力服务。但office365仅仅只应用于移动办公吗&#xff1f;有没有可能实现移动办学呢&#xff1f;仅仅是商业智能吗&#xff1f;会不会也能做到教学智能&#xff1f;上海蓝盟连续…

python连接数据库mysql错误1045、手动登录可以_登录mysql错误1045解决方法

在命令提示符中登陆mysql时&#xff0c;提示1045报错解决方案&#xff1a; 安装好mysql&#xff0c;在cmd中输入mysql -uroot -p回车&#xff0c;输入密码后&#xff0c;出现1045错误&#xff0c;错误提示如下&#xff1a; ERROR 1045(28000): Access denied for user rootloca…

host 端口_如何让多端口网站用一个nginx进行反向代理实际场景分析

前段时间公司要整合服务器资源&#xff0c;刚好趁这次机会将这些乱七八糟的服务器做一次梳理和整合&#xff0c;断断续续一个月迁移完成大概优化掉了1/3的机器&#xff0c;完成之后遇到了一些问题&#xff0c;比如曾今零零散散部署在生产上一些可视化UI&#xff1a;apollo&…

sqldeveloper导出数据字典_如何全面建设B端产品中的数据迁移方案

加关注&#xff0c;带你看世界在新系统替换老系统或者系统升级的项目中&#xff0c;难免会存在数据迁移的工作&#xff0c;并且随着业务系统和数据结构的复杂性&#xff0c;数据迁移的难度越大。这亦要求在项目实施的前期&#xff0c;根据客户的需求尽可能全面地考虑到各个方面…

声明对象_静态变量(使用同一个类声明的对象可以共享一个值)

要在属于同一种类的对象之间共享数据值&#xff0c;可以使用static。namespace demo3{ class point //定义点 { public int x; public int y; } class line { static public point origin new point(); public point ending ne…