Apache Doris 行列转换可以这样玩
行列转换在做报表分析时还是经常会遇到的,今天就说一下如何实现行列转换吧。
行列转换就是如下图所示两种展示形式的互相转换
1. 行转列
我们来看一个简单的例子,我们要把下面这个表的数据,转换成图二的样式
image-20230914151818953.png
要转换的结果数据展示
image-20230914152642915.png
先看看建表语句:
CREATE TABLE tb_score_01(id INT(11) NOT NULL,userid VARCHAR(20) NOT NULL COMMENT '用户id',subject VARCHAR(20) COMMENT '科目',score DOUBLE COMMENT '成绩'
)
DUPLICATE KEY(`id`)
COMMENT 'OLAP'
DISTRIBUTED BY HASH(`id`) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"in_memory" = "false",
"storage_format" = "V2",
"light_schema_change" = "true",
"disable_auto_compaction" = "false"
);INSERT INTO tb_score_01 VALUES (1,'001','语文',90);
INSERT INTO tb_score_01 VALUES (2,'001','数学',92);
INSERT INTO tb_score_01 VALUES (3,'001','英语',80);
INSERT INTO tb_score_01 VALUES (4,'002','语文',88);
INSERT INTO tb_score_01 VALUES (5,'002','数学',90);
INSERT INTO tb_score_01 VALUES (6,'002','英语',75.5);
INSERT INTO tb_score_01 VALUES (7,'003','语文',70);
INSERT INTO tb_score_01 VALUES (8,'003','数学',85);
INSERT INTO tb_score_01 VALUES (9,'003','英语',90);
INSERT INTO tb_score_01 VALUES (10,'003','政治',82);
传统的做法我们大概是这样实现,一般是通过 case when
语句
SELECT userid,
SUM(CASE `subject` WHEN '语文' THEN score ELSE 0 END) as '语文',
SUM(CASE `subject` WHEN '数学' THEN score ELSE 0 END) as '数学',
SUM(CASE `subject` WHEN '英语' THEN score ELSE 0 END) as '英语',
SUM(CASE `subject` WHEN '政治' THEN score ELSE 0 END) as '政治'
FROM tb_score
GROUP BY userid;或者SELECT userid,
SUM(IF(`subject`='语文',score,0)) as '语文',
SUM(IF(`subject`='数学',score,0)) as '数学',
SUM(IF(`subject`='英语',score,0)) as '英语',
SUM(IF(`subject`='政治',score,0)) as '政治'
FROM tb_score
GROUP BY userid;
我们来看看 Doris 怎么实现这个行转列呢,有没有更简单、性能更好的一种方式
-
我们是不是可以首先将这个科目、成绩组成一个Map
-
然后在外层对这个 Map 进行遍历展开
-
从而完成这样一个行列转换呢
我们来看看实现
select userid,IFNULL(map['语文'],0) as '语文',IFNULL(map['英语'],0) as '英语',IFNULL(map['数学'],0) as '数学',IFNULL(map['政治'],0) as '政治'
from (select userid ,map_agg(subject,score) as map from tb_score group by userid
) t ;
这样实现上性能更好,我们来看一下效果
select-> userid,-> IFNULL(map['语文'],0) as '语文',-> IFNULL(map['英语'],0) as '英语',-> IFNULL(map['数学'],0) as '数学',-> IFNULL(map['政治'],0) as '政治'-> from (-> select userid ,map_agg(subject,score) as map from tb_score group by userid-> ) t ;
+--------+--------+--------+--------+--------+
| userid | 语文 | 英语 | 数学 | 政治 |
+--------+--------+--------+--------+--------+
| 001 | 90 | 80 | 92 | 0 |
| 002 | 88 | 75.5 | 90 | 0 |
| 003 | 70 | 90 | 85 | 82 |
+--------+--------+--------+--------+--------+
3 rows in set (0.02 sec)
2. 列转行
实际使用中我们还有很多场景要把数据冲列转成行,下面我们来看一个例子,这个例子中每行是一个学生的,语文、数学、英语、政治的成绩,
image-20230914152642915.png
我们想转换成每门成绩都是独立的一行,转出的效果如下:
image-20230914152846996.png
我们来看看一个宽表转成高表我们之前的是怎么实现,一般我们是通过union all的方式,每科我们都是一个单独的SQL语句,然后将这些SQL Unoin all 在一起得到我们想要的结果。
SELECT userid,'语文' AS course,cn_score AS score FROM tb_score1
UNION ALL
SELECT userid,'数学' AS course,math_score AS score FROM tb_score1
UNION ALL
SELECT userid,'英语' AS course,en_score AS score FROM tb_score1
UNION ALL
SELECT userid,'政治' AS course,po_score AS score FROM tb_score1
ORDER BY userid;
这样做的缺点:
-
SQL 冗余
-
大量的union all 也会带来性能问题
我们来看看 Doris 怎么实现,首先 Doris 提供了 Lateral view,其实就是用来和像类似explode这种UDTF函数联用的,lateral view会将 UDTF 生成的结果放到一个虚拟表中,然后这个虚拟表
会和输入行
进行 join
来达到连接 UDTF 外的 select 字段的目的
还是以上面的例子来看,Doris我怎么对这个宽表转成高表,实现就是借助Lateral view
CREATE TABLE `tb_score1` (`id` int(11) NOT NULL,`userid` varchar(20) NOT NULL COMMENT '用户id',`cn_score` double NULL COMMENT '语文成绩',`math_score` double NULL COMMENT '数学成绩',`en_score` double NULL COMMENT '英语成绩',`po_score` double NULL COMMENT '政治成绩'
) ENGINE=OLAP
UNIQUE KEY(`id`)
COMMENT 'OLAP'
DISTRIBUTED BY HASH(`id`) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"is_being_synced" = "false",
"storage_format" = "V2",
"light_schema_change" = "true",
"disable_auto_compaction" = "false",
"enable_single_replica_compaction" = "false"
);;INSERT INTO `tb_score1` (`id`, `userid`, `cn_score`, `math_score`, `en_score`, `po_score`) VALUES (1, '001', 90, 92, 80, 0);
INSERT INTO `tb_score1` (`id`, `userid`, `cn_score`, `math_score`, `en_score`, `po_score`) VALUES (2, '002', 88, 90, 75.5, 0);
INSERT INTO `tb_score1` (`id`, `userid`, `cn_score`, `math_score`, `en_score`, `po_score`) VALUES (3, '003', 70, 85, 90, 82);
- 首先我借助Lateral view 形成一个 UserID、客户成绩组成一个字符(使用逗号连接),达到下面的效果
+--------+--------------------+
| userid | arr |
+--------+--------------------+
| 001 | ["语文", "90"] |
| 001 | ["数学", "92"] |
| 001 | ["英语", "80"] |
| 001 | ["政治", "0"] |
| 002 | ["语文", "88"] |
| 002 | ["数学", "90"] |
| 002 | ["英语", "75.5"] |
| 002 | ["政治", "0"] |
| 003 | ["语文", "70"] |
| 003 | ["数学", "85"] |
| 003 | ["英语", "90"] |
| 003 | ["政治", "82"] |
+--------+--------------------+
12 rows in set (0.02 sec)
-
然后对这个上面的 arr 字符串,借助于 Doris 提供的 SPLIT_BY_STRING 函数完成字符串转数组的动作
-
最后遍历数组
-
完成列转行的效果
SELECTuserid,element_at ( arr, 1 ) AS SUBJECT,element_at ( arr, 2 ) AS score
FROM(SELECTuserid,SPLIT_BY_STRING ( sub, ',' ) arr FROM(SELECTuserid,array (concat( '语文', ',', cn_score ),concat( '数学', ',', math_score ),concat( '英语', ',', en_score ),concat( '政治', ',', po_score )) AS scores FROMtb_score1 ) t LATERAL VIEW explode ( scores ) tbl1 AS sub ) aaa
最后的效果如下:
SELECT-> userid,-> element_at ( arr, 1 ) AS SUBJECT,-> element_at ( arr, 2 ) AS score-> FROM-> (-> SELECT-> userid,-> SPLIT_BY_STRING ( sub, ',' ) arr-> FROM-> (-> SELECT-> userid,-> array (-> concat( '语文', ',', cn_score ),-> concat( '数学', ',', math_score ),-> concat( '英语', ',', en_score ),-> concat( '政治', ',', po_score )) AS scores-> FROM-> tb_score1-> ) t LATERAL VIEW explode ( scores ) tbl1 AS sub-> ) aaa;
+--------+---------+-------+
| userid | SUBJECT | score |
+--------+---------+-------+
| 001 | 语文 | 90 |
| 001 | 数学 | 92 |
| 001 | 英语 | 80 |
| 001 | 政治 | 0 |
| 002 | 语文 | 88 |
| 002 | 数学 | 90 |
| 002 | 英语 | 75.5 |
| 002 | 政治 | 0 |
| 003 | 语文 | 70 |
| 003 | 数学 | 85 |
| 003 | 英语 | 90 |
| 003 | 政治 | 82 |
+--------+---------+-------+
12 rows in set (0.02 sec)
日记本
相关文章:
Apache Doris 行列转换可以这样玩
行列转换在做报表分析时还是经常会遇到的,今天就说一下如何实现行列转换吧。 行列转换就是如下图所示两种展示形式的互相转换 1. 行转列 我们来看一个简单的例子,我们要把下面这个表的数据,转换成图二的样式 image-20230914151818953.png …...
【Qt图形视图框架】自定义QGraphicsItem和QGraphicsView,实现鼠标(移动、缩放)及键盘事件、右键事件
自定义QGraphicsItem和QGraphicsView 说明示例myitem.hmyitem.cppmyview.hmyview.cpp调用main.cpp 效果 说明 在使用Qt的图形视图框架实现功能时,一般会在其基础上进行自定义功能实现。 如:滚轮对场景的缩放,鼠标拖动场景中的项,…...
C语言结构体指针学习
结构体变量存放内存中,也有起始地址,定义一个变量来存放这个地址,那这个变量就是结构体指针; typedef struct mydata{int a1;int a2;int a3; }mydata;void CJgtzzView::OnDraw(CDC* pDC) {CJgtzzDoc* pDoc GetDocument();ASSERT…...
华为云云耀云服务器L实例评测|部署在线轻量级备忘录 memos
华为云云耀云服务器L实例评测|部署在线轻量级备忘录 memos 一、云耀云服务器L实例介绍1.1 云服务器介绍1.2 产品优势1.3 应用场景1.4 支持镜像 二、云耀云服务器L实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 memos3.1 memos介绍3.2 Docker 环境搭建…...
详解Avast Driver Updater:电脑驱动更新工具的利器还是多余的软件?
亲爱的读者朋友们,你是不是经常为电脑的驱动问题而烦恼?如果是的话,你可能会对这款软件——Avast Driver Updater 电脑驱动更新工具感兴趣。但在你决定尝试之前,不妨先和我一起深入探讨一下它的优点、缺点以及它适用的使用场景。 …...
大数据Flink(九十五):DML:Window TopN
文章目录 DML:Window TopN DML:Window TopN Window TopN 定义(支持 Streaming):Window TopN 是一种特殊的 TopN,它的返回结果是每一个窗口内的 N 个最小值或者最大值。 应用场景...
使用OKHttpClient访问网络
使用OKHttpClient前要引入依赖: 在build.gradle(Moduel :app)中添加 implementation com.squareup.okhttp3:okhttp:3.14.1 implementation com.squareup.okhttp3:logging-interceptor:3.14.1 implementation com.squareup.okio:okio:1.6.0 1. GET(同步…...
maui 开发AMD CPU踩的坑。
刚换的 amd R7735HS 笔记本,8核16线程,32GB内存。性能得实强悍 。 当需要发布iOS版本时发现,我没有macos ,那就安装个vmware 吧。看了一下Apple 要求以后的发布的APP需要以xcode14.3或以后版本开发的版本,但xcode14.3…...
宝塔反代openai官方API接口详细教程,502 Bad Gateway问题解决
一、前言 宝塔反代openai官方API接口详细教程,实现国内使用ChatGPT502 Bad Gateway问题解决, 此方法最简单快捷,没有复杂步骤,不容易出错,即最简单,零代码、零部署的方法。 二、实现前提 一台海外VPS服务…...
【leetocde】128. 最长连续序列
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入:nums [100,4,200,1,3,2] 输出:4 …...
【Vue3】动态 class 类
如果你想在 Vue.js 中动态设置元素的 class 类名,你可以使用以下两种主要方式: 绑定一个动态的 class 对象:你可以使用 v-bind 或简写的 : 来绑定一个包含类名的对象,其中类名的键是类名字符串,值是一个布尔值或计算属…...
【Redis】redis基本数据类型详解(String、List、Hash、Set、ZSet)
目录 RedisString(字符串)List(列表)Hash(字典)Set(集合)ZSet(有序集合) Redis Redis有5种基本的数据结构,分别为:string(字符串)、list(列表)、set(集合)、hash(哈希&a…...
ubuntu源码安装aria2
github:GitHub - aria2/aria2: aria2 is a lightweight multi-protocol & multi-source, cross platform download utility operated in command-line. It supports HTTP/HTTPS, FTP, SFTP, BitTorrent and Metalink. 发行说明:GitHub - aria2/aria2 at releas…...
【多任务案例:猫狗脸部定位与分类】
【猫狗脸部定位与识别】 1 引言2 损失函数3 The Oxford-IIIT Pet Dataset数据集4 数据预处理4 创建模型输入5 自定义数据集加载方式6 显示一批次数据7 创建定位模型8 模型训练9 绘制损失曲线10 模型保存与预测 1 引言 猫狗脸部定位与识别分为定位和识别,即定位猫狗…...
.Net 锁的介绍
在.NET中,有多种锁机制可用于多线程编程,用来确保线程安全和共享资源的同步。以下是.NET中常见的锁机制: 1. **Monitor(互斥锁):** `Monitor` 是.NET中最基本的锁机制之一。它使用 `lock` 关键字实现,可以确保在同一时刻只有一个线程能够访问被锁定的代码块。`Monitor`…...
Office 2021 小型企业版商用办公软件评测:提升工作效率与协作能力的专业利器
作为一名软件评测人员,我将为您带来一篇关于 Office 2021 小型企业版商用办公软件的评测文章。在这篇评测中,我将从实用性、使用场景、优点和缺点等多个方面对该软件进行客观分析,在专业角度为您揭示它的真正实力和潜力。 一、实用性…...
Monkey测试
一:测试环境搭建 1:下载android-sdk_r24.4.1-windows 2:下载Java 3:配置环境变量:关于怎么配置环境变量(百度一下:monkey环境搭建,) 二:monkey测试࿱…...
wzx-jmw:NFL合理,但可能被颠覆。2023-2024
As well known by all, NFL is ... 没有免费的午餐理论 No Free Lunch Theorem_免费午餐理论-CSDN博客 However, if we......
密码技术 (5) - 数字签名
一. 前言 前面在介绍消息认证码时,我们知道消息认证码虽然可以确认消息的完整性,但是无法防止否认问题。而数字签名可以解决否认的问题,接下来介绍数字签名的原理。 二. 数字签名的原理 数字签名和公钥密码一样,也有公钥和私钥&am…...
php实战案例记录(10)单引号和双引号的用法和区别
在 PHP 中,单引号和双引号都被用于表示字符串。它们有一些共同之处,但也有一些明显的区别。 解析变量: 双引号允许解析变量,而单引号不会。在双引号中,你可以直接在字符串中插入变量,而不需要进行额外的连接…...
嵌入式Linux应用开发-基础知识-第十九章驱动程序基石②
嵌入式Linux应用开发-基础知识-第十九章驱动程序基石② 第十九章 驱动程序基石②19.3 异步通知19.3.1 适用场景19.3.2 使用流程19.3.3 驱动编程19.3.4 应用编程19.3.5 现场编程19.3.6 上机编程19.3.7 异步通知机制内核代码详解 19.4 阻塞与非阻塞19.4.1 应用编程19.4.2 驱动编程…...
trycatch、throw、throws
在Java中,try-catch、throw和throws是用于处理异常的重要关键字和机制,它们的作用如下: try-catch:try-catch 是用于捕获和处理异常的语句块。在try块中放置可能引发异常的代码。如果在try块中的代码引发了异常,控制流会跳转到与异常类型匹配的catch块。在catch块中,可以…...
问 ChatGPT 关于 GPT 的事情:数据准备篇
一、假如你是一名人工智能工程师,手里有一个65B的GPT大模型,但你需要一个6B左右的小模型,你会怎么做? 答:作为人工智能工程师,如果我手里有一个65B的GPT大模型,而我需要一个6B左右的小模型&…...
leetcode_17电话号码的组合
1. 题意 输出电话号码对应的字母左右组合 电话号码的组合 2. 题解 回溯 class Solution { public:void gen_res(vector<string> &res, vector<string> &s_m,string &digits, string &t, size_t depth) {if (depth digits.size()) {if ( !t.em…...
记录使用vue-test-utils + jest 在uniapp中进行单元测试
目录 前情安装依赖package.json配置jest配置测试文件目录编写setup.js编写第一个测试文件jest.fn()和jest.spyOn()jest 解析scss失败测试vuex$refs定时器测试函数调用n次手动调用生命周期处理其他模块导入的函数测试插槽 前情 uniapp推荐了测试方案dcloudio/uni-automator&…...
《C和指针》笔记30:函数声明数组参数、数组初始化方式和字符数组的初始化
文章目录 1. 函数声明数组参数2. 数组初始化方式2.1 静态初始化2.2 自动变量初始化 2.2 字符数组的初始化 1. 函数声明数组参数 下面两个函数原型是一样的: int strlen( char *string ); int strlen( char string[] );可以使用任何一种声明,但哪个“更…...
VBA技术资料MF64:遍历单元格搜索字符并高亮显示
【分享成果,随喜正能量】不要在乎他人的评论,不必理论与他人有关的是非,你只要做好自己就够了。苔花如米小,也学牡丹开。无论什么时候,都要有忠于自己的勇气,去做喜欢的事,去认识喜欢的人&#…...
一键智能视频编辑与视频修复算法——ProPainter源码解析与部署
前言 视频编辑和修复确实是随着电子产品的普及变得越来越重要的技能。有许多视频编辑工具可以帮助人们轻松完成这些任务如:Adobe Premiere Pro,Final Cut Pro X,Davinci Resolve,HitFilm Express,它们都提供一些视频修…...
Flutter开发环境的配置
2023-10最新版本 flutter SDK版本下载地址 https://flutter.cn/docs/development/tools/sdk/releases gradle各版本快速下载地址 https://blog.csdn.net/ii950606/article/details/109105402 JAVA SDK下载地址 https://www.oracle.com/java/technologies/downloads/#java…...
【超详细】Wireshark教程----Wireshark 分析ICMP报文数据试验
一,试验环境搭建 1-1 试验环境示例图 1-2 环境准备 两台kali主机(虚拟机) kali2022 192.168.220.129/24 kali2022 192.168.220.3/27 1-2-1 网关配置: 编辑-------- 虚拟网路编辑器 更改设置进来以后 ,先选择N…...
甘肃兰州流感最新消息/南京百度seo代理
我们在内存里可以串起一棵树, 但是我们总得想办法保存下来。 比如机器要关了,内存里的东西都要销毁了, 我们需要怎么样才能将指针那些东西保存成文件的格式!以便于我们下回重建出这棵树。 这就是本节要讲的 序列化和反序列化的问题…...
无锡高端网站建设公司哪家好/楚雄今日头条新闻
题意 题目链接 Sol 比较套路吧,设\(f[i][j]\)表示以\(i\)为根的子树中选了\(j\)个黑点对答案的贡献 然后考虑每条边的贡献,边的两边的答案都是可以算出来的 转移的时候背包一下。 #include<bits/stdc.h> #define Pair pair<int, int> #defin…...
公司微信网站制作/企业如何开展网络营销
---layout: posttitle: "linux ssd bug"date: 2019-09-30categories: hardware---# 1. bug 描述安装了 manjaro 的 xps 9350,睡眠长时间放电后,无法启动系统。现象:- 电脑可以正常启动 bios, 可以进入 grub, 选择 manjaro 后无法找…...
做外汇看新闻在什么网站看/开发小程序
这里是重点,<ripple>是API21才有的新Tag,正是实现水波纹效果的; 其中<ripple android:color"#FF21272B" .... />这个是指定水波纹的颜色. 而<item />里面的东西,我们都很熟悉,就是普通的定义一个带圆角的背景. ripple_bg.xml: <?xml version&q…...
东莞网站设计公司/搭建网站平台需要多少钱
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼说明:以下文件名及文件夹名均不区分大小写,而且所有字母和数字都是英文半角字符。(1)、建立名称为IT的文件夹,并在文件夹下建立如下文件夹结构:IT————打印机——扫描仪——数码相…...
视频网站是如何做的/会员制营销方案
2019独角兽企业重金招聘Python工程师标准>>> 1.ListView滑动方向判断 代码很简单,给mListView监听onScrollListener事件,然后在onScroll进行判断 //listView中第一项的索引private int mListViewFirstItem 0;//listView中第一项的在屏幕中的…...