DLA SQL技巧:行、列转换和JSON数据列展开

1. 简介

在数据库SQL处理中,常常有行转列(Pivot)和列转行(Unpivot)的数据处理需求。本文以示例说明在Data Lake Analytics中,如何使用SQL的一些技巧,达到行转列(Pivot)和列转行(Unpivot)的目的。另外,DLA支持函数式表达式的处理逻辑、丰富的JSON数据处理函数和UNNEST的SQL语法,结合这些功能,能够实现非常丰富、强大的SQL数据处理语义和能力,本文也以JSON数据列展开为示例,说明在DLA中使用这种SQL的技巧。

2. 行转列(Pivot)

2.1 样例数据

test_pivot表内容:

+------+----------+---------+--------+
| id   | username | subject | source |
+------+----------+---------+--------+
| 1    | 张三     | 语文    | 60     |
| 2    | 李四     | 数学    | 70     |
| 3    | 王五     | 英语    | 80     |
| 4    | 王五     | 数学    | 75     |
| 5    | 王五     | 语文    | 57     |
| 6    | 李四     | 语文    | 80     |
| 7    | 张三     | 英语    | 100    |
+------+----------+---------+--------+

2.2 方法一:通过CASE WHEN语句

SQL语句:

SELECT username,max(CASE WHEN subject = '语文' THEN source END) AS `语文`,max(CASE WHEN subject = '数学' THEN source END) AS `数学`,max(CASE WHEN subject = '英语' THEN source END) AS `英语`
FROM test_pivot
GROUP BY username
ORDER BY username;

结果:

+----------+--------+--------+--------+
| username | 语文   | 数学   | 英语   |
+----------+--------+--------+--------+
| 张三     | 60     | NULL   | 100    |
| 李四     | 80     | 70     | NULL   |
| 王五     | 57     | 75     | 80     |
+----------+--------+--------+--------+

2.3 方法二:通过map_agg函数

该方法思路上分为两个步骤:
第一步,通过map_agg函数把两个列的多行的值,映射为map;
第二步,通过map的输出,达到多列输出的目的。

第一步SQL:

SELECT username, map_agg(subject, source) kv
FROM test_pivot
GROUP BY username
ORDER BY username;

第一步输出:

+----------+-----------------------------------+
| username | kv                                |
+----------+-----------------------------------+
| 张三     | {语文=60, 英语=100}               |
| 李四     | {数学=70, 语文=80}                |
| 王五     | {数学=75, 语文=57, 英语=80}       |
+----------+-----------------------------------+

可以看到map_agg的输出效果。

最终,该方法的SQL:

SELECTusername,if(element_at(kv, '语文') = null, null, kv['语文']) AS `语文`,if(element_at(kv, '数学') = null, null, kv['数学']) AS `数学`,if(element_at(kv, '英语') = null, null, kv['英语']) AS `英语`
FROM (SELECT username, map_agg(subject, source) kvFROM test_pivotGROUP BY username
) t
ORDER BY username;

结果:

+----------+--------+--------+--------+
| username | 语文   | 数学   | 英语   |
+----------+--------+--------+--------+
| 张三     | 60     | NULL   | 100    |
| 李四     | 80     | 70     | NULL   |
| 王五     | 57     | 75     | 80     |
+----------+--------+--------+--------+

3. 列转行(Unpivot)

3.1 样例数据

test_unpivot表内容:

+----------+--------+--------+--------+
| username | 语文   | 数学   | 英语   |
+----------+--------+--------+--------+
| 张三     | 60     | NULL   | 100    |
| 李四     | 80     | 70     | NULL   |
| 王五     | 57     | 75     | 80     |
+----------+--------+--------+--------+

3.2 方法一:通过UNION语句

SQL语句:

SELECT username, subject, source
FROM (SELECT username, '语文' AS subject, `语文` AS source FROM test_unpivot WHERE `语文` is not nullUNIONSELECT username, '数学' AS subject, `数学` AS source FROM test_unpivot WHERE `数学` is not nullUNIONSELECT username, '英语' AS subject, `英语` AS source FROM test_unpivot WHERE `英语` is not null
)
ORDER BY username;

结果:

+----------+---------+--------+
| username | subject | source |
+----------+---------+--------+
| 张三     | 语文    | 60     |
| 张三     | 英语    | 100    |
| 李四     | 语文    | 80     |
| 李四     | 数学    | 70     |
| 王五     | 英语    | 80     |
| 王五     | 语文    | 57     |
| 王五     | 数学    | 75     |
+----------+---------+--------+

3.3 方法二:通过CROSS JOIN UNNEST语句

SQL语句:

SELECT t1.username, t2.subject, t2.source
FROM test_unpivot t1
CROSS JOIN UNNEST (array['语文', '数学', '英语'],array[`语文`, `数学`, `英语`]
) t2 (subject, source)
WHERE t2.source is not null

结果:

+----------+---------+--------+
| username | subject | source |
+----------+---------+--------+
| 张三     | 语文    | 60     |
| 张三     | 英语    | 100    |
| 李四     | 语文    | 80     |
| 李四     | 数学    | 70     |
| 王五     | 语文    | 57     |
| 王五     | 数学    | 75     |
| 王五     | 英语    | 80     |
+----------+---------+--------+

4. JSON数据列展开

JSON数据的表达能力非常灵活,因此在数据库和SQL中,常常需要处理JSON数据,常常碰到稍复杂的需求,就是将JSON数据中的某些属性字段,进行展开转换,转成行、列的关系型表达。

4.1 基本思路和步骤

  • 使用JSON函数,对JSON字符串进行解析和数据提取;
  • 提取、转换为ARRAY或者MAP的数据结构,如有需要,可以使用Lambda函数式表达式进行转换处理;
  • 利用UNNEST语法进行列展开。

下面以多个示例说明。

4.2 用UNNEST对MAP进行关系型展开

SQL示例:

SELECT t.m, t.n
FROM (SELECT MAP(ARRAY['foo', 'bar'], ARRAY[1, 2]) as map_data
)
CROSS JOIN unnest(map_data) AS t(m, n);

结果:

+------+------+
| m    | n    |
+------+------+
| foo  |    1 |
| bar  |    2 |
+------+------+

4.3 用UNNEST对JSON数据进行关系型展开

SQL示例:

SELECT json_extract(t.a, '$.a') AS a, json_extract(t.a, '$.b') AS b
FROM (SELECT cast(json_extract('{"x":[{"a":1,"b":2},{"a":3,"b":4}]}', '$.x') AS array<JSON>) AS package_array
)
CROSS JOIN UNNEST(package_array) AS t(a);

结果:

+------+------+
| a    | b    |
+------+------+
| 1    | 2    |
| 3    | 4    |
+------+------+

SQL示例:

SELECT t.m AS _col1, t.n AS _col2
FROM (SELECT cast(json_extract('{"x":[{"a":1,"b":2},{"a":3,"b":4}]}', '$.x') AS array<JSON>) AS array_1, cast(json_extract('{"x":[{"a":5,"b":6}, {"a":7,"b":8}, {"a":9,"b":10}, {"a":11,"b":12}]}', '$.x') AS array<JSON>) AS array_2
)
CROSS JOIN UNNEST(array_1, array_2) AS t(m, n);

结果:

+---------------+-----------------+
| _col1         | _col2           |
+---------------+-----------------+
| {"a":1,"b":2} | {"a":5,"b":6}   |
| {"a":3,"b":4} | {"a":7,"b":8}   |
| NULL          | {"a":9,"b":10}  |
| NULL          | {"a":11,"b":12} |
+---------------+-----------------+

SQL示例:

SELECT json_extract(t.m, '$.a') AS _col1, json_extract(t.m, '$.b') AS _col2, json_extract(t.n, '$.a') AS _col3, json_extract(t.n, '$.b') AS _col4 
FROM (SELECT cast(json_extract('{"x":[{"a":1,"b":2},{"a":3,"b":4}]}', '$.x') AS array<JSON>) AS array_1, cast(json_extract('{"x":[{"a":5,"b":6}, {"a":7,"b":8}, {"a":9,"b":10}, {"a":11,"b":12}]}', '$.x') AS array<JSON>) AS array_2
)
CROSS JOIN UNNEST(array_1, array_2) AS t(m, n);

结果:

+-------+-------+-------+-------+
| _col1 | _col2 | _col3 | _col4 |
+-------+-------+-------+-------+
| 1     | 2     | 5     | 6     |
| 3     | 4     | 7     | 8     |
| NULL  | NULL  | 9     | 10    |
| NULL  | NULL  | 11    | 12    |
+-------+-------+-------+-------+

4.4 结合Lambda表达式,用UNNEST对JSON数据进行关系型展开

SQL示例:

SELECT count(*) AS cnt, package_name 
FROM ( SELECT t.a AS package_name FROM ( SELECT transform(packages_map_array, x -> Element_at(x, 'packageName')) AS package_array FROM (SELECT cast(Json_extract(data_json, '$.packages') AS array<map<VARCHAR, VARCHAR>>) AS packages_map_arrayFROM (SELECT json_parse(data) AS data_jsonFROM ( SELECT '{"packages": [{"appName": "铁路12306","packageName": "com.MobileTicket","versionName": "4.1.9","versionCode": "194"},{"appName": "QQ飞车","packageName": "com.tencent.tmgp.speedmobile","versionName": "1.11.0.13274","versionCode": "1110013274"},{"appName": "掌阅","packageName": "com.chaozh.iReaderFree","versionName": "7.11.0","versionCode": "71101"}]}'AS data ))) ) AS x (package_array)CROSS JOIN UNNEST(package_array) AS t (a)
)
GROUP BY package_name 
ORDER BY cnt DESC;

结果:

+------+------------------------------+
| cnt  | package_name                 |
+------+------------------------------+
|    1 | com.MobileTicket             |
|    1 | com.tencent.tmgp.speedmobile |
|    1 | com.chaozh.iReaderFree       |
+------+------------------------------+


原文链接
本文为云栖社区原创内容,未经允许不得转载。

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

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

相关文章

看完这一篇,你就对 Spring Security 略窥门径了 | 原力计划

作者 | BoCong-Deng来源 | CSDN 博客&#xff0c;责编 | 夕颜头图 | CSDN 下载自东方 IC出品 | CSDN&#xff08;ID:CSDNnews&#xff09;写在前面开发Web应用&#xff0c;对页面的安全控制通常是必须的。比如&#xff1a;对于没有访问权限的用户需要转到登录表单页面。要实现访…

Java-冒泡排序

public class ArrayDemo07 {public static void main(String[] args) {int[] a {3,5,1,7,8,4};int[] sort sort(a);System.out.println(Arrays.toString(sort)); // [1, 3, 4, 5, 7, 8]}/*每次将 最大 或 最小的数 后移*/public static int[] sort(int[] array){// 临时变量…

借助 Cloud Toolkit 快速创建 Dubbo 工程

Cloud Toolkit 是一个 IDE 插件&#xff0c;帮助开发者更高效地开发、测试、诊断并部署应用。在最新版的插件中&#xff0c;提供了快速创建 Dubbo 工程的功能&#xff0c;下面就来快速体验下吧。 Dubbo 采用全 Spring 配置方式&#xff0c;透明化接入应用&#xff0c;对应用没…

vue-cli-service不是内部或外部命令,也不是可运行的程序

报错信息: “不是内部或外部命令&#xff0c;也不是可运行的程序” 步骤一: 检查package.json 中是否有 vue-cli-server,没有则需安装 步骤二 : 执行npm install命令 npm run serve

另一种声音:容器是不是未来?

作者 | Ian Eyberg译者 | 天道酬勤 责编 | 徐威龙封图| CSDN 下载于视觉中国CSDN 云计算旨在为读者提供更多角度的声音&#xff0c;本文仅代表作者个人观点&#xff0c;不代表CSDN云计算任何立场。前几天作者看到了这则推文&#xff0c;可以这么说&#xff0c;是它促使我开始就…

从 Spark Streaming 到 Apache Flink : 实时数据流在爱奇艺的演进

本文将为大家介绍Apache Flink在爱奇艺的生产与实践过程。你可以借此了解到爱奇艺引入Apache Flink的背景与挑战&#xff0c;以及平台构建化流程。主要内容如下&#xff1a; 爱奇艺在实时计算方面的的演化和遇到的一些挑战爱奇艺使用Flink的User Case爱奇艺Flink平台化构建流程…

Java-稀疏数组

public class ArrayDemo08 {public static void main(String[] args) {// 1. 创建一个二维数组 11*11 0: 没有棋子 1: 黑棋 2: 白棋int[][] array1 new int[11][11];array1[1][2] 1;array1[2][3] 2;// 输出原始的数组System.out.println("输出原始的数组");for…

揭秘|每秒千万级的实时数据处理是怎么实现的?

1、设计背景 闲鱼目前实际生产部署环境越来越复杂&#xff0c;横向依赖各种服务盘宗错节&#xff0c;纵向依赖的运行环境也越来越复杂。当服务出现问题的时候&#xff0c;能否及时在海量的数据中定位到问题根因&#xff0c;成为考验闲鱼服务能力的一个严峻挑战。 线上出现问题…

Vue3.x 使用ref和reactive、toRef

文章目录一、使用ref1. 引入2. 定义ref变量3. 赋值.value4. return 返回值5. 将数据渲染到页面二、使用reactive 和 toRef1. 引入2. 定义reactive变量3. 赋值变量.对象4. return 返回值5. 将数据渲染到页面三、效果图源码3.1. 效果图3.2. 源码一、使用ref 1. 引入 从vue里面引…

同学,要不要来挑战双11零点流量洪峰?

阿里妹导读&#xff1a;双十一的零点&#xff0c;整个电商系统的请求速率到达峰值。如果将这些请求流量只分配给少部分 server&#xff0c;这些机器接收到的请求速率会远超过处理速率&#xff0c;新来的任务来不及处理&#xff0c;就会产生请求任务堆积。 今年的中间件性能挑战…

GitHub 疑遭中间人攻击,最大暗网托管商再被黑!

整理 | 伍杏玲出品 | 程序人生&#xff08;ID&#xff1a;coder_life&#xff09;近期&#xff0c;在全球关注新冠肺炎疫情之际&#xff0c;黑客却频频动作&#xff0c;发动攻击&#xff1a;GitHub 疑遭中间人攻击&#xff0c;无法访问从26日下午开始&#xff0c;有网友表示国内…

Java-什么是面向对象

https://www.bilibili.com/video/BV12J41137hu?p60

Jenkins Pipeline脚本优化:为Kubernetes应用部署增加状态检测

引言 在软件部署的世界中&#xff0c;Jenkins已经成为自动化流程的代名词。不断变化的技术环境要求我们持续改进部署流程以满足现代应用部署的需要。在本篇博客中&#xff0c;作为一位资深运维工程师&#xff0c;我将分享如何将Jenkins Pipeline进化至不仅能支持部署应用直至R…

Flink 零基础实战教程:如何计算实时热门商品

在上一篇入门教程中&#xff0c;我们已经能够快速构建一个基础的 Flink 程序了。本文会一步步地带领你实现一个更复杂的 Flink 应用程序&#xff1a;实时热门商品。在开始本文前我们建议你先实践一遍上篇文章&#xff0c;因为本文会沿用上文的my-flink-project项目框架。 通过…

Apache Flink 结合 Kafka 构建端到端的 Exactly-Once 处理

文章目录&#xff1a; Apache Flink 应用程序中的 Exactly-Once 语义Flink 应用程序端到端的 Exactly-Once 语义示例 Flink 应用程序启动预提交阶段在 Flink 中实现两阶段提交 Operator总结 Apache Flink 自2017年12月发布的1.4.0版本开始&#xff0c;为流计算引入了一个重要的…

一文教你如何使用 MongoDB 和 HATEOAS 创建 REST Web 服务

作者 | Ion Pascari译者 | 天道酬勤 责编 | 徐威龙封图| CSDN 下载于视觉中国最近&#xff0c;作者在把HATEOAS实现到REST Web服务时遇到了一件有趣的事情&#xff0c;而且他也很幸运地尝试了一个名为MongoDB的NoSQL数据库&#xff0c;他发现该数据库在许多不需要管理实务的不同…

Java-值传递和引用传递

值传递 // 值传递 public class Demo04 {public static void main(String[] args) {int a 1;System.out.println(a); // 1change(a);System.out.println(a); // 1}public static void change(int a){a 10;} }引用传递 // 引用传递&#xff1a; 对象, 本质还是值传递 publ…

使用NGINX作为HTTPS正向代理服务器

NGINX主要设计作为反向代理服务器&#xff0c;但随着NGINX的发展&#xff0c;它同样能作为正向代理的选项之一。正向代理本身并不复杂&#xff0c;而如何代理加密的HTTPS流量是正向代理需要解决的主要问题。本文将介绍利用NGINX来正向代理HTTPS流量两种方案&#xff0c;及其使用…

flowable 表名sql mysql和oracle

mysql ### 工作流相关表增加表注释SQLalter table act_evt_log comment 事件日志表–EventLogEntryEntityImpl; alter table act_ge_bytearray comment 流程xml存储表; alter table act_ge_property comment 流程版本信息&#xff0c;禁止私自修改; alter table act_hi_actins…

IoT SaaS加速器——助力阿尔茨海默病人护理

场景介绍 阿尔茨海默病&#xff0c;是导致中老年人认知功能障碍的最常见疾病之一&#xff0c;是发生在老年期及老年前期的一种原发性退行性脑病。据估计&#xff0c;全世界痴呆症患者数量为4700万&#xff0c;到2030年将达到7500万人。痴呆症患者数量到2050年预计将是现在的近…