SQL concat_ws, collect_set, 和explode合并使用
1. 背景
有一个这样的数据集:字段和字段的值是两列

目的是将这个数据转换成规整的一个特征是一列的数据:

2. 做法
第一步:先造出列
select ucid
,CASE WHEN type ='性别' THEN label end `性别`
,CASE WHEN type ='产品' THEN label end `产品`
,CASE WHEN type ='还款表现' THEN label end `还款表现`
,CASE WHEN type ='营业点' THEN label end `营业点`
,CASE WHEN type ='base' THEN label end `base`
From input

第二步:多行合并为一行

select ucid
,concat_ws(',',collect_set(CASE WHEN type ='性别' THEN label end)) `性别`
,concat_ws(',',collect_set(CASE WHEN type ='产品' THEN label end)) `产品`
,concat_ws(',',collect_set(CASE WHEN type ='还款表现' THEN label end)) `还款表现`
,concat_ws(',',collect_set(CASE WHEN type ='营业点' THEN label end)) `营业点`
,concat_ws(',',collect_set(CASE WHEN type ='base' THEN label end)) `base`
From input
group by `ucid`
第三步:特征枚举值展开
select ucid, explode(split(`产品`,',')) as `产品` from (
select ucid
,concat_ws(',',collect_set(CASE WHEN type ='性别' THEN label end)) `性别`
,concat_ws(',',collect_set(CASE WHEN type ='产品' THEN label end)) `产品`
,concat_ws(',',collect_set(CASE WHEN type ='还款表现' THEN label end)) `还款表现`
,concat_ws(',',collect_set(CASE WHEN type ='营业点' THEN label end)) `营业点`
,concat_ws(',',collect_set(CASE WHEN type ='base' THEN label end)) `base`
From input
group by `ucid`
)

上面是示范展开一列。由于一个select里只能有一个explode,因此,为了得到最终想要的数据,需要explode多层(哭哭)
select ucid, `性别`, `产品explode`, `还款表现explode`, `营业点explode`, `base` ,explode(split(`营业点`,',')) as `营业点explode` from (
select *, explode(split(`还款表现`,',')) as `还款表现explode` from (
select *, explode(split(`产品`,',')) as `产品explode` from (
select ucid
,concat_ws(',',collect_set(CASE WHEN type ='性别' THEN label end)) `性别`
,concat_ws(',',collect_set(CASE WHEN type ='产品' THEN label end)) `产品`
,concat_ws(',',collect_set(CASE WHEN type ='还款表现' THEN label end)) `还款表现`
,concat_ws(',',collect_set(CASE WHEN type ='营业点' THEN label end)) `营业点`
,concat_ws(',',collect_set(CASE WHEN type ='base' THEN label end)) `base`
From input
group by `ucid`
)))

其实 spark SQL 3.3.2可以用lateral view 实现一次explode多个字段:
https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select-lateral-view.html

CREATE TABLE person (id INT, name STRING, age INT, class INT, address STRING);
INSERT INTO person VALUES
(100, 'John', 30, 1, 'Street 1'),
(200, 'Mary', NULL, 1, 'Street 2'),
(300, 'Mike', 80, 3, 'Street 3'),
(400, 'Dan', 50, 4, 'Street 4');
SELECT * FROM person
LATERAL VIEW EXPLODE(ARRAY(30, 60)) tableName AS c_age
LATERAL VIEW EXPLODE(ARRAY(40, 80)) AS d_age;
3. 函数
1. concat_ws 和concat的联系与区别
concat(col1, col2, ..., colN) - Returns the concatenation of col1, col2, ..., colN.,可以拼接多个字符串
concat_ws(sep[, str | array(str)]+) - Returns the concatenation of the strings separated by sep.返回用指定分隔符进行拼接的字符串,指定的分隔符放在第一个参数位置,后面的参数默认为需要进行拼接的字符串。
二者的区别在于:
concat中若有一个参数为null ,则返回null。而concat_ws,不会因为存在null 值就返回null 。
select concat("-","DS","A", "B",null) from input

select concat_ws("-","DS","A", "B",null) from input

2. collect_set 函数
collect_set(expr) - Collects and returns a set of unique elements.
3. explode 函数
explode里面的参数,可以是 array ,也可以是 map
explode(expr) - Separates the elements of array expr into multiple rows, or the elements of map expr into multiple rows and columns. Unless specified otherwise, uses the default column name col for elements of the array or key and value for the elements of the map
select explode(array(10, 20)) from input

array如果需要分割,需要和split嵌套使用
SELECT explode(split('1,2,3',',')) from input

SELECT explode(map('A','1','B','2','C','3')) from input

时间的展开:
select `date`,`min_date`,`max_date`,
explode(sequence(
`min_date`,`max_date`,interval 1 day
)) as `展开日期`
# day是day颗粒度,也可以换成month
SQL concat_ws, collect_set, 和explode合并使用的更多相关文章
- Expression构建DataTable to Entity 映射委托 sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。 sql server 多行数据合并成一列 C# 字符串大写转小写,小写转大写,数字保留,其他除外 从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法 纯CSS打造淘宝导航菜单栏 C# Winform
Expression构建DataTable to Entity 映射委托 1 namespace Echofool.Utility.Common { 2 using System; 3 using ...
- 在论坛中出现的比较难的sql问题:18(字符合并 整数解析星期几)
原文:在论坛中出现的比较难的sql问题:18(字符合并 整数解析星期几) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得 ...
- 如何用SQL脚本在SQL Server Replication中创建合并复制,以及怎么创建分区合并复制
假设我们要创建合并复制的发布端数据库是EFDemo其中有四张表,订阅端数据库是EFDemoSubscription,如下图所示: 首先创建发布端快照代理Sql agent job:"EFDe ...
- SQL将多行数据合并成一行【转】
转:https://blog.csdn.net/AntherFantacy/article/details/83824182 今天同事问了一个需求,就是将多行数据合并成一行进行显示,查询了一些资料,照 ...
- SQL SERVER 2008 字段值合并
/** * 通过 FOR XML PATH 语句,可以将字段的值进行合并. **/ CREATE TABLE tb_child ( name ), hobby ) ) go INSERT INTO t ...
- SQL Server 联表字段合并查询
经常遇到统计报表中,子表记录合并为一个字段的情况.例如:省表中各省经济水平前五的城市统计. 有如下两表:dbo.省 和 dbo.市 (好吧,你可能会吐槽为什么用中文表名,其实我是为了方便查找替换) 这 ...
- sql server 多行数据合并成一列
首先是源数据: ),cip.CheckIn_StartTime, )),cip.CheckIn_EndTime, )),cip.Rental_Price)) as content from Check ...
- sql 把多列内容合并
这个语句不完整.应该是这样:stuff(select ',' + fieldname from tablename for xml path('')),1,1,'') as ’别名‘这一整句的作用是 ...
- sql 内连接 子查询 合并查询
-- 内连接:-- 显示员工姓名.工资和公司所在地 select e.ename, e.sal, d.dname from emp e,dept d; -- 笛卡尔积 select e.ename, ...
- SQL编程:group by合并结果字符串 ---> group_concat函数就能行
1.表结构 create table tt(id int,v varchar(30)); insert into tt values(1,'a'),(1,'b'),(2,'b ...
随机推荐
- MySQL分库分表原理
转自https://www.jianshu.com/p/7aec260ca1a2 前言 在互联网还未崛起的时代,我们的传统应用都有这样一个特点:访问量.数据量都比较小,单库单表都完全可以支撑整个业务. ...
- MySQL数据库封锁机制和事务隔离级别
参考: 数据库技术:MySql学习笔记之事务隔离级别详解 详解MySQL 数据库隔离级别与MVCC MySQL 事务&&锁机制&&MVCC 数据库系统原理 - MySQ ...
- CSS网页布局基础
CSS网页布局基础1.行布局-基础的行布局-行布局自适应-行布局自适应限制最大宽-行布局垂直水平居中-行布局某部位自适应-行布局固定宽-行布局导航随屏幕滚动2.多列布局-两列布局固定-两列布局自适应- ...
- 使用hugo在gitee上写blog
1. 安装hugo 1)下载 Hugo Releases,选择hugo_xxx_Windows-64bit.zip(xxx位版本). 2)设置路径 我的电脑->属性->高级系统设置-> ...
- pod控制器
Pod控制器介绍 Pod是kubernetes的最小管理单元,在kubernetes中,按照pod的创建方式可以将其分为两类: 自主式pod:kubernetes直接创建出来的Pod,这种pod删除后 ...
- windows系统,自动设置--shutdown命令了解
参考:https://baike.baidu.com/item/shutdown/10469108?fr=aladdin 比如你的电脑要在24:00关机,可以选择"开始运行",输入 ...
- unity更改c#文件名的小tip
今天偶然知道了一个在Unity中更改代码文件名的小技巧--最好先在Unity的project视图里找到文件,改完后再去visual studio等代码编辑器里改里面的类名. 以前都没注意,想起来要改某 ...
- lc.209 长度最小的子数组
题目 给定一个含有 n 个正整数的数组和一个正整数 target . 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, n ...
- Nginx配置ThinkPHP3.1的PATHINFO模式
location / { if (!-e $request_filename) { rewrite ^/(.*)$ /index.php?$1 last; bre ...
- Windows软件堆栈溢出(stack overflow)的一些解决方法
欢迎访问我的个人博客:xie-kang.com 原文地址 Windows平台下,有三种方法调整堆栈大小(适用于MSVC编译器): 1)添加编译参数:/F size #其中size的单位是byte可设 ...