您当前的位置:首页 > 电脑百科 > 数据库 > 百科

SQL实用技巧-行列转换

时间:2024-05-17 11:53:53  来源:  作者:凉凉的知识库

在编写大数据SQL的时候,有时需要进行行列的转化。

什么是行列转化?如下图,不同商品在不同月份的销量数据,有时候我们希望数据和左侧一样的排列,但原始数据却像右侧一样排列,此时我们需要把右侧的列排列转换成左侧的行排列,反之亦然。

行转列与列转行行转列与列转行

下面以上面这个例子为大家介绍一些行列转换的方式。

行转列

使用CASE WHEN

适用场景:MySQL、Hive、Spark SQL。

把行转换成列最简单的方式就是使用CASE WHEN。

case month when '2024-01' then sales end的意思是当month的值为'2024-01'时取sales的值,其他情况取NULL,因此可以计算出不同月份的销量。

select  product
        ,max(case month when '2024-01' then sales end) as month_01
        ,max(case month when '2024-02' then sales end) as month_02
        ,max(case month when '2024-03' then sales end) as month_03
from    sales_row
group by product

使用PIVOT

适用场景:Spark SQL。

PIVOT关键字对于指定的每一组行值,都会生成对应的列。PIVOT关键字是FROM子句的一部分,可以和JOIN等其他关键字一同使用。

SELECT ... 
FROM ... 
PIVOT ( 
    <aggregate function> [AS <alias>] [, <aggregate function> [AS <alias>]] ... 
    FOR (<column> [, <column>] ...) 
    IN ( 
        (<value> [, <value>] ...) AS <new column> 
        [, (<value> [, <value>] ...) AS <new column>] 
        ... 
       ) 
    ) 
[...]

参数

是否必选

说明

aggregate function

聚合函数

alias

聚合函数的别名,别名和最终PIVOT处理过后生成的列名相关

column

指定转换为列的行值在源表中的列名称

value

指定转换为列的行值

new column

转换后新的列名称

直接看示例。

利用PIVOT把month列按值聚合出了三列month_01,month_02,month_03。

select  *
from    sales_row 
PIVOT (
     MAX(sales) for month in(
       '2024-01' as month_01, 
       '2024-02' as month_02, 
       '2024-03' as month_03
     )
)

列转行

使用UNION ALL

适用场景:MySQL、Hive、Spark SQL。

UNION ALL相当于取每一个列的值,然后并联在一起,注意'2024-01' as month中的2024-01是字符串。

使用UNION ALL的好处就是,无论是mysql、hive还是spark都支持,以不变应万变。

缺点就是当要关联列比较多时比较麻烦,如果要查询全年的数据,则需要UNION ALL 12次,如果是天数据则要UNION ALL 365次。

select  *
from    (
    select product, '2024-01' as month, month_01 from sales_column
    union all
    select product, '2024-02' as month, month_02 from sales_column
    union all
    select product, '2024-03' as month, month_03 from sales_column
)

仅使用EXPLODE

适用场景:Spark SQL。

explode可以将一个数组或者map分解成多行,例如:

select explode(split('A,B,C', ','))

# 结果
col
A
B
C
select explode(map('2024-01', 1000, '2024-02', 2000, '2024-03', 3000))

# 结果
key     value
2024-01 1000
2024-02 2000
2024-03 3000

对于列转行的需求,可以先创建一个map之后再利用explode拆分成多行。

注意下面SQL中,explode函数返回值有两个,因此设置列别名时需要用as (month, sales)。

select  product
        ,explode(
          map('2024-01', month_01, 
              '2024-02', month_02, 
              '2024-03', month_03)
        ) as (month, sales)
from    sales_column

类似的思路还可以利用concat+trans_array等操作。

hive中的UDTF

上面的方式仅适用于Spark。

当使用UDTF函数(explode就是一个UDTF函数)的时候,Hive只允许对拆分字段进行访问。

select explode(map('2024-01', 1000, '2024-02', 2000, '2024-03', 3000))

# 结果
key     value
2024-01 1000
2024-02 2000
2024-03 3000

也就是说在Hive中,上面SQL是没问题的,下面的SQL就会报错了

hive> select  product
    >   ,explode(map('2024-01', month_01, '2024-02', month_02, '2024-03', month_03))
  >  from    sales_column

SemanticException [Error 10081]: UDTF's are not supported outside the SELECT clause, nor nested in expressions

因此这块需要使用LATERAL VIEW功能来进行处理。LATERAL VIEW将explode生成的结果当做一个视图来处理。

使用Lateral View

适用场景:Hive、Spark SQL。

lateral view为侧视图,意义是为了配合UDTF来使用,把某一行数据拆分成多行数据。

Hive中不加lateral view的UDTF只能提取单个字段拆分。加上lateral view就可以将拆分的单个字段数据与原始表数据关联上。

LATERAL VIEW [ OUTER ] generator_function ( expression [ , ... ] ) [ table_alias ] AS column_alias [ , ... ]

参数

是否必选

说明

generator_function

将一行数据拆成多行数据的UDTF (EXPLODE, INLINE等)

table_alias

UDTF结果的别名

columnAlias

拆分后得到的列的别名

直接看如何利用lateral view实现列转行。

select  product, t_view.month, t_view.sales
from    sales_column
lateral view explode(
    map('2024-01', month_01, '2024-02', month_02, '2024-03', month_03)
) t_view as month, sales

其中explode(map('2024-01', month_01, '2024-02', month_02, '2024-03', month_03))把map分解成多行。

lateral view同时指定了这个侧视的表名t_view和两列的列名month 、sales。

lateral view explode(
    map('2024-01', month_01, '2024-02', month_02, '2024-03', month_03)
) t_view as month, sales

# 模拟结果,lateral view不能单独使用
month sales
2024-01 1000
2024-02 1100
2024-03 1200
2024-01 1100
2024-02 1000
2024-03 1400

此时select product, t_view.month, t_view.sales就能达成UDTF拆分的单个字段数据与原始表数据关联的效果了。

select  product, t_view.month, t_view.sales
from    sales_column

# 结果
product month sales
A 2024-01 1000
A 2024-02 1100
A 2024-03 1200
B 2024-01 1100
B 2024-02 1000
B 2024-03 1400

使用UNPIVOT

适用场景:Spark 3.4+。

UNPIVOT关键字对于指定的每一组列,都会生成对应的行。其中UNPIVOT关键字是FROM子句的一部分,可以和JOIN关键字等其他关键字一同使用。

SELECT ...
FROM ...
UNPIVOT (
  <new column of value> [, <new column of value>] ...
  FOR (<new column of name> [, <new column of name>] ...)
  IN (
      (<column> [, <column>] ...) [AS (<column value> [, <column value>] ...)]
      [, (<column> [, <column>] ...) [AS (<column value> [, <column value>] ...)]]
      ...
    )
)
[...]

参数说明如下:

参数

是否必选

说明

new column of value

转换后新生成的列名称,该列的值由指定转换为行的列的值填充。

new column of name

转换后新生成的列名称,该列的值由指定转换为行的列名称填充。

column

指定转换为行的列名称,列的名称用来填充new column of name;列的值用来填充new column of value。

column value

指定转换为行的列的别名

也是直接看示例:

select  *
from    sales_column 
UNPIVOT (
  sales for month in (month_01 as '2024-01', month_02 as '2024-02', month_03 as '2024-03')
)

sales for month in (month_01, month_02, month_03)的意思就是生成一个新列sales,这一列的值是month_01, month_02, month_03这三列的值。

生成一个新列month, 这里一列的值是month_01, month_02, month_03这三列的列名,即'2024-01',  '2024-02', '2024-03'。



Tags:SQL   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
SQL实用技巧-行列转换
在编写大数据SQL的时候,有时需要进行行列的转化。什么是行列转化?如下图,不同商品在不同月份的销量数据,有时候我们希望数据和左侧一样的排列,但原始数据却像右侧一样排列,此时我...【详细内容】
2024-05-17  Search: SQL  点击:(0)  评论:(0)  加入收藏
掌握这八个方法,精通SQL日期函数
在数据库管理中,处理日期和时间数据是一项常见任务。SQL提供了丰富的日期函数来执行对日期和时间值的各种操作。在本文中,我们将探讨SQL日期函数、其语法、实际应用以及说明其...【详细内容】
2024-05-15  Search: SQL  点击:(5)  评论:(0)  加入收藏
从MongoDB到PostgreSQL:数据零丢失、成本砍半
Infisical 是一家开源的密钥管理平台,为团队及基础设施提供同步密钥的服务并防止密钥泄露。随着业务不断发展、数据不断增加,原有数据库已无法满足当前需求,Infisical 决定从 M...【详细内容】
2024-05-15  Search: SQL  点击:(4)  评论:(0)  加入收藏
MySQL 核心模块揭秘
1. 概述MySQL 采用插件化存储引擎,从这个角度,整体结构可以分为两层: server 层。 存储引擎。基于以上两层结构,MySQL 的锁也可以分为两大类。server 层的锁,就是让我们头痛不已...【详细内容】
2024-05-15  Search: SQL  点击:(3)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-05-13  Search: SQL  点击:(2)  评论:(0)  加入收藏
MySQL误删数据怎么办?
今天给大家介绍一个很常见的数据库面试题:MySQL误删数据怎么办?大家都知道数据库最重要的就是数据,数据安全是重中之重,对于这种事后面试题,其实面试者回答一些提前规划,比如提前...【详细内容】
2024-04-23  Search: SQL  点击:(13)  评论:(0)  加入收藏
 为什么MySQL默认使用RR隔离级别?
对于数据库的默认隔离级别,Oracle默认的隔离级别是 RC,而MySQL默认的隔离级别是 RR。那么,你知道为什么Oracle选择RC作为默认级别,而MySQL要选择RR作为默认的隔离级别吗?Oracle的...【详细内容】
2024-04-23  Search: SQL  点击:(12)  评论:(0)  加入收藏
GitHub是怎样把MySQL 5.7升级到8.0的?
去年(2023年10月25日),随着MySQL 5.7.44发布,宣告5.7正式停止开发和维护。而不少企业选择把MySQL 5.7升级到8.0。那么你所在的公司,现在使用了哪些MySQL版本呢?GitHub也在去年把My...【详细内容】
2024-04-12  Search: SQL  点击:(11)  评论:(0)  加入收藏
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  Search: SQL  点击:(18)  评论:(0)  加入收藏
原来 SQL 函数是可以内联的!
介绍在某些情况下,SQL 函数(即指定LANGUAGE SQL)会将其函数体内联到调用它的查询中,而不是直接调用。这可以带来显著的性能提升,因为函数体可以暴露给调用查询的规划器,从而规划器...【详细内容】
2024-04-03  Search: SQL  点击:(15)  评论:(0)  加入收藏
▌简易百科推荐
SQL实用技巧-行列转换
在编写大数据SQL的时候,有时需要进行行列的转化。什么是行列转化?如下图,不同商品在不同月份的销量数据,有时候我们希望数据和左侧一样的排列,但原始数据却像右侧一样排列,此时我...【详细内容】
2024-05-17  凉凉的知识库    Tags:SQL   点击:(0)  评论:(0)  加入收藏
掌握这八个方法,精通SQL日期函数
在数据库管理中,处理日期和时间数据是一项常见任务。SQL提供了丰富的日期函数来执行对日期和时间值的各种操作。在本文中,我们将探讨SQL日期函数、其语法、实际应用以及说明其...【详细内容】
2024-05-15    Python学研大本营  Tags:SQL   点击:(5)  评论:(0)  加入收藏
从MongoDB到PostgreSQL:数据零丢失、成本砍半
Infisical 是一家开源的密钥管理平台,为团队及基础设施提供同步密钥的服务并防止密钥泄露。随着业务不断发展、数据不断增加,原有数据库已无法满足当前需求,Infisical 决定从 M...【详细内容】
2024-05-15    dbaplus社群  Tags:MongoDB   点击:(4)  评论:(0)  加入收藏
如何使用图数据库提高向量搜索精确度?
文本嵌入和向量搜索技术可以帮助我们根据文档的含义及其相似性来检索文档。但当需要根据日期或类别等特定标准来筛选信息时,这些技术就显得力不从心。为了解决这个问题,我们可...【详细内容】
2024-04-29    AI小智  Tags:数据库   点击:(8)  评论:(0)  加入收藏
线上MongoDB查询慢,如何通过索引优化直降响应时间?
作者 | 吴守阳审校 | 重楼背景线上某个页面的响应速度异常缓慢,达到了16秒,严重影响了业务的正常运行。经过与研发的沟通得知,该页面调用的数据集合只会保留7天的数据,集合有600...【详细内容】
2024-04-29    51CTO  Tags:MongoDB   点击:(10)  评论:(0)  加入收藏
MongoDB索引使用总结
MongoDB索引使用总结MongoDB 是目前最流行的文档型数据库。MongoDB 的采用类 json 的存储格式对开发者来说非常友好。本文梳理了 MongoDB 索引的底层结构以及使用经验,不足之...【详细内容】
2024-04-17  视角先锋队    Tags:MongoDB   点击:(8)  评论:(0)  加入收藏
向量数据库落地实践
本文基于京东内部向量数据库vearch进行实践。Vearch 是对大规模深度学习向量进行高性能相似搜索的弹性分布式系统。详见: https://github.com/vearch/zh_docs/blob/v3.3.X/do...【详细内容】
2024-04-03  京东云开发者    Tags:向量数据库   点击:(19)  评论:(0)  加入收藏
原来 SQL 函数是可以内联的!
介绍在某些情况下,SQL 函数(即指定LANGUAGE SQL)会将其函数体内联到调用它的查询中,而不是直接调用。这可以带来显著的性能提升,因为函数体可以暴露给调用查询的规划器,从而规划器...【详细内容】
2024-04-03  红石PG  微信公众号  Tags:SQL 函数   点击:(15)  评论:(0)  加入收藏
如何正确选择NoSQL数据库
译者 | 陈峻审校 | 重楼Allied Market Research最近发布的一份报告指出,业界对于NoSQL数据库的需求正在持续上升。2022年,全球NoSQL市场的销售额已达73亿美元,预计到2032年将达...【详细内容】
2024-03-28    51CTO  Tags:NoSQL   点击:(44)  评论:(0)  加入收藏
为什么数据库连接池不采用 IO 多路复用?
这是一个非常好的问题。IO多路复用被视为是非常好的性能助力器。但是一般我们在使用DB时,还是经常性采用c3p0,tomcat connection pool等技术来与DB连接,哪怕整个程序已经变成以...【详细内容】
2024-03-27  dbaplus社群    Tags:数据库连接池   点击:(28)  评论:(0)  加入收藏
站内最新
站内热门
站内头条