【SQL开发实战技巧】系列(三十四):数仓报表场景☞如何对数据分级并行转为列

news/2025/1/18 11:07:43/

系列文章目录

【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事
【SQL开发实战技巧】系列(二):简单单表查询
【SQL开发实战技巧】系列(三):SQL排序的那些事
【SQL开发实战技巧】系列(四):从执行计划讨论UNION ALL与空字符串&UNION与OR的使用注意事项
【SQL开发实战技巧】系列(五):从执行计划看IN、EXISTS 和 INNER JOIN效率,我们要分场景不要死记网上结论
【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放
【SQL开发实战技巧】系列(七):从有重复数据前提下如何比较出两个表中的差异数据及对应条数聊起
【SQL开发实战技巧】系列(八):聊聊如何插入数据时比约束更灵活的限制数据插入以及怎么一个insert语句同时插入多张表
【SQL开发实战技巧】系列(九):一个update误把其他列数据更新成空了?Merge改写update!给你五种删除重复数据的写法!
【SQL开发实战技巧】系列(十):从拆分字符串、替换字符串以及统计字符串出现次数说起
【SQL开发实战技巧】系列(十一):拿几个案例讲讲translate|regexp_replace|listagg|wmsys.wm_concat|substr|regexp_substr常用函数
【SQL开发实战技巧】系列(十二):三问(如何对字符串字母去重后按字母顺序排列字符串?如何识别哪些字符串中包含数字?如何将分隔数据转换为多值IN列表?)
【SQL开发实战技巧】系列(十三):讨论一下常用聚集函数&通过执行计划看sum()over()对员工工资进行累加
【SQL开发实战技巧】系列(十四):计算消费后的余额&计算银行流水累计和&计算各部门工资排名前三位的员工
【SQL开发实战技巧】系列(十五):查找最值所在行数据信息及快速计算总和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report
【SQL开发实战技巧】系列(十六):数据仓库中时间类型操作(初级)日、月、年、时、分、秒之差及时间间隔计算
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
【SQL开发实战技巧】系列(十八):数据仓库中时间类型操作(进阶)INTERVAL、EXTRACT以及如何确定一年是否为闰年及周的计算
【SQL开发实战技巧】系列(十九):数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期?
【SQL开发实战技巧】系列(二十):数据仓库中时间类型操作(进阶)获取季度开始结束时间以及如何统计非连续性时间的数据
【SQL开发实战技巧】系列(二十一):数据仓库中时间类型操作(进阶)识别重叠的日期范围,按指定10分钟时间间隔汇总数据
【SQL开发实战技巧】系列(二十二):数仓报表场景☞ 从分析函数效率一定快吗聊一聊结果集分页和隔行抽样实现方式
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
【SQL开发实战技巧】系列(二十四):数仓报表场景☞通过案例执行计划详解”行转列”,”列转行”是如何实现的
【SQL开发实战技巧】系列(二十五):数仓报表场景☞结果集中的重复数据只显示一次以及计算部门薪资差异高效的写法以及如何对数据进行快速分组
【SQL开发实战技巧】系列(二十六):数仓报表场景☞聊聊ROLLUP、UNION ALL是如何分别做分组合计的以及如何识别哪些行是做汇总的结果行
【SQL开发实战技巧】系列(二十七):数仓报表场景☞通过对移动范围进行聚集来详解分析函数开窗原理以及如何一个SQL打印九九乘法表
【SQL开发实战技巧】系列(二十八):数仓报表场景☞人员分布问题以及不同组(分区)同时聚集如何实现
【SQL开发实战技巧】系列(二十九):数仓报表场景☞简单的树形(分层)查询以及如何确定根节点、分支节点和叶子节点
【SQL开发实战技巧】系列(三十):数仓报表场景☞树形(分层)查询如何排序?以及如何在树形查询中正确的使用where条件
【SQL开发实战技巧】系列(三十一):数仓报表场景☞分层查询如何只查询树形结构某一个分支?如何剪掉一个分支?
【SQL开发实战技巧】系列(三十二):数仓报表场景☞对表中某个字段内的值去重
【SQL开发实战技巧】系列(三十三):数仓报表场景☞从不固定位置提取字符串的元素以及搜索满足字母在前数字在后等条件的数据
【SQL开发实战技巧】系列(三十四):数仓报表场景☞如何对数据分级并行转为列


文章目录

  • 系列文章目录
  • 前言
  • 一、把结果分级并转为列
    • 1、生成序号
    • 2、按照一定要求(我这里随意)
    • 3、要对三列数据重新生成序号
  • 总结


前言

本篇文章讲解的主要内容是:有个需求:把emp中的结果按工资分级,其中最高的三档作为一列、次高的三档作为一列、其余的作为一列。本篇文章我们来讨论下这个需求怎么实现。给出case when 和pivot两种行转列的方法。通过此案例理解隐藏列信息的重要性。
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。


一、把结果分级并转为列

现在有个需求:把emp中的结果按工资分级,其中最高的三档作为一列、次高的三档作为一列、其余的作为一列。
本篇文章我们来讨论下这个需求怎么实现。该问题解决思路如下:

1、生成序号

这里让数据相同的(3000)排序相同,且不占排序位置,所以需要用dense_rank
来生成序号:

with t as (
select ename,sal,dense_rank()over(order by sal desc) as rn
from emp
)
select * from t;
ENAME            SAL         RN
---------- --------- ----------
KING         5000.00          1
FORD         3000.00          2
SCOTT        3000.00          2
JONES        2975.00          3
BLAKE        2850.00          4
CLARK        2450.00          5
ALLEN        1600.00          6
TURNER       1500.00          7
MILLER       1300.00          8
WARD         1250.00          9
MARTIN       1250.00          9
ADAMS        1100.00         10
JAMES         950.00         11
SMITH         800.00         1214 rows selected

从上面查询结果可看到(FORD,SCOTT)sal都为3000,排序序号rn都为2。

2、按照一定要求(我这里随意)

将上面数据划分为三档,这可通过CASE WHEN完成:

with t as(select ename, sal, dense_rank() over(order by sal desc) as rn from emp)
select t.*,casewhen rn <= 3 then1when rn <= 6 then2else3end as new_rnfrom t;
ENAME            SAL         RN     NEW_RN
---------- --------- ---------- ----------
KING         5000.00          1          1
FORD         3000.00          2          1
SCOTT        3000.00          2          1
JONES        2975.00          3          1
BLAKE        2850.00          4          2
CLARK        2450.00          5          2
ALLEN        1600.00          6          2
TURNER       1500.00          7          3
MILLER       1300.00          8          3
WARD         1250.00          9          3
MARTIN       1250.00          9          3
ADAMS        1100.00         10          3
JAMES         950.00         11          3
SMITH         800.00         12          314 rows selected

3、要对三列数据重新生成序号

这样行转列时才能把序号相同的归为一行:

with t as(select ename, sal, dense_rank() over(order by sal desc) as rn from emp),
t1 as(select t.*,casewhen rn <= 3 then1when rn <= 6 then2else3end as new_rnfrom t)
select t1.*, row_number() over(partition by new_rn order by sal) as flagfrom t1
ENAME            SAL         RN     NEW_RN       FLAG
---------- --------- ---------- ---------- ----------
JONES        2975.00          3          1          1
FORD         3000.00          2          1          2
SCOTT        3000.00          2          1          3
KING         5000.00          1          1          4
ALLEN        1600.00          6          2          1
CLARK        2450.00          5          2          2
BLAKE        2850.00          4          2          3
SMITH         800.00         12          3          1
JAMES         950.00         11          3          2
ADAMS        1100.00         10          3          3
MARTIN       1250.00          9          3          4
WARD         1250.00          9          3          5
MILLER       1300.00          8          3          6
TURNER       1500.00          7          3          714 rows selected

4、根据最后生成的“分组”列进行“行转列”即可

with t as --l.对数据分档(select ename, sal, dense_rank() over(order by sal desc) as rn from emp),
t1 as --2.根据档次把数据分为三类(select t.*,casewhen rn <= 3 then1when rn <= 6 then2else3end as new_rnfrom t),
t2 as --3.分别对三列的数据重新取序号,这样相同序号的可以汇总后放在同一行(select t1.*, row_number() over(partition by new_rn order by sal) as flagfrom t1)
--4.行转列
select max(case new_rnwhen 1 thenename || '(' || sal || ')'end) as 第一档,max(case new_rnwhen 2 thenename || '(' || sal || ')'end) as 第二档,max(case new_rnwhen 3 thenename || '(' || sal || ')'end) as 第三档from t2group by flagorder by flag;
第一档                                                                           第二档                                                                           第三档
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
JONES(2975)                                                                      ALLEN(1600)                                                                      SMITH(800)
FORD(3000)                                                                       CLARK(2450)                                                                      JAMES(950)
SCOTT(3000)                                                                      BLAKE(2850)                                                                      ADAMS(1100)
KING(5000)                                                                                                                                                        MARTIN(1250)WARD(1250)MILLER(1300)TURNER(1500)7 rows selected

上面写法使用的是case when的方式写的,下面再给一个用pivot的写法:

with t as --l.对数据分档(select ename, sal, dense_rank() over(order by sal desc) as rn from emp),
t1 as --2.根据档次把数据分为三类(select t.*,casewhen rn <= 3 then1when rn <= 6 then2else3end as new_rnfrom t),
t2 as --3.分别对三列的数据重新取序号,这样相同序号的可以汇总后放在同一行(select t1.*, row_number() over(partition by new_rn order by sal) as flagfrom t1)
--4.行转列
select max(第一档), max(第二档), max(第三档)from (select ename || '(' || sal || ')' as enames, new_rn, flag from t2)
pivot (max(enames) for new_rn in(1 as 第一档,2 as 第二档,3 as 第三档))group by flag;
MAX(第一档)                                                                      MAX(第二档)                                                                      MAX(第三档)
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
JONES(2975)                                                                      ALLEN(1600)                                                                      SMITH(800)
FORD(3000)                                                                       CLARK(2450)                                                                      JAMES(950)
SCOTT(3000)                                                                      BLAKE(2850)                                                                      ADAMS(1100)
KING(5000)                                                                                                                                                        MARTIN(1250)WARD(1250)MILLER(1300)TURNER(1500)7 rows selected

排序后生成的行号属于隐含信息,而这种隐含信息常用在各种复杂的查询中。对于这种查询,当你知道需要哪种隐含信息时,你就成功了一半!!!


总结

本篇文章讲解的主要内容是:有个需求:把emp中的结果按工资分级,其中最高的三档作为一列、次高的三档作为一列、其余的作为一列。本篇文章我们来讨论下这个需求怎么实现。给出case when 和pivot两种行转列的方法。通过此案例理解隐藏列信息的重要性。


http://www.ppmy.cn/news/37098.html

相关文章

TypeScript学习笔记一

文章目录一、类型注解二、TypeScript常用类型2.1 原始类型2.2 数组类型2.3 联合类型2.4 类型别名2.5 给函数添加类型2.6 对象类型2.7 对象的可选属性2.8 接口2.9 interface和type的对比2.10 接口继承2.11 元组2.12 类型推断2.13 类型断言2.14 字面量类型2.15 枚举2.16 any类型2…

选择很重要,骑友,怎么挑选骑行装备?

骑行装备的重要性&#xff0c;已经不用多说了&#xff0c;大家也都知道。但是如何挑选&#xff0c;如何选择适合自己的骑行装备呢&#xff1f;今天我来和大家聊一聊这个问题。首先我们需要了解一个概念&#xff1a;骑行装备分为两大类&#xff1a;骑行服和骑行鞋。对于公路车来…

Git常用指令

Git是什么&#xff1a; Git是分布式版本控制系统&#xff08;Distributed Version Control System&#xff0c;简称 DVCS&#xff09;&#xff0c;分为两种类型的仓库&#xff1a; 本地仓库和远程仓库 第一步先新建仓库&#xff0c;本地 init ,然后提交分枝 链接仓库&#xf…

★DDR相关

1.速率&#xff0c;电压 DDR3&#xff1a;800-2133Mbps&#xff1b;1.5V&#xff08;VDDQ&#xff09; DDR4&#xff1a;1600-3200Mbps&#xff1b;1.2V&#xff08;VDDQ&#xff09; 1&#xff1a;tCK1.25ns&#xff0c;芯片支持最大IO时钟频率&#xff08;DDR3频率&#xf…

TensorFlow详解1

一、TensorFlow详细架构 1、前端&#xff08;编程模型采用python、c、java&#xff09; 2、后端&#xff08;运行采用c&#xff09; 二、TensorFlow特点 1、灵活性&#xff1a;只要可以将计算表示成数据流图&#xff0c;就可以使用TensorFlow&#xff1b; 2、跨平台性&…

jwt 的鉴权过程与安全性分析

&#xff08;一&#xff09;讲一下jwt 鉴权原理 JWT&#xff08;JSON Web Token&#xff09;是一种基于标准JSON格式的轻量级身份认证和授权协议。JWT由三部分组成&#xff1a;Header&#xff08;头部&#xff09;、Payload&#xff08;载荷&#xff09;和Signature&#xff0…

八 SpringMVC【拦截器】登录验证

目录&#x1f6a9;一 SpringMVC拦截器✅ 1.配置文件✅2.登录验证代码&#xff08;HandlerInterceptor&#xff09;✅3.继承HandlerInterceptorAdapter&#xff08;不建议使用&#xff09;✅4.登录页面jsp✅5.主页面&#xff08;操作页面&#xff09;✅6.crud用户在访问页面时 只…

【Linux面试】-(腾讯,百度,美团,滴滴)

文章目录Linux 面试题-(腾讯,百度,美团,滴滴) 分析日志 t.log(访问量)&#xff0c;将各个 ip 地址截取&#xff0c;并统计出现次数,并按从大到小排序(腾讯) http://192.168.200.10/index1.html http://192.168.200.10/index2.html http://192.168.200.20/index1.html http://19…