Spark SQL的高级用法

一. 快速生成多行的序列

需求:请生成一列数据, 内容为 1 , 2 , 3 , 4 ,5

-- 快速生成多行的序列
-- 方式一
select explode(split("1,2,3,4,5",","));
--方式二
/*
 序列函数sequence(start,stop,step):生成指定返回的列表数据
 [start,stop]必须传入,step步长可传可不传,默认为1,也可以传入负数,传入负数的时候,大数要在前,小数
 */
select explode(sequence(1,5));
select explode(sequence(1,5,1));
select explode(sequence(1,5,2));
select explode(sequence(5,1,-1));
select explode(sequence(5,1,-2));

二. 快速生成表数据

需求: 生成一个两行两列的数据, 第一行放置 男 M 第二行放置 女 F

-- 快速生成表数据
/*
 stack(n,expr1, ..., exprk),n代表要分为n行,expr1, ..., exprk是放入每一行每一列的元素
 如果不传入列名,则默认使用col0,col1等作为列名
 */
select stack(2,"男","M","女","F");
select stack(2,"男","M","女","F") as (n,v);

三. 如何将一个SQL的结果给到另外一个SQL进行使用

3.1 视图

临时视图关键字:temporary

  1. 分为永久视图临时视图
  2. 相同点:都不会真正的存储数据。主要是用来简化SQL语句
  3. 不同点:永久试图会创建元数据,在多个会话(Session)中都有效;临时视图只在当前会话有效

3.2 视图和表的区别

视图不会真正的存储数据,而表会真正的存储数据。
但是视图和表在使用的时候区别不大

-- 如何将一个SQL的结果给到另外一个SQL进行使用
-- 方式一:子查询
select
    *
from (select stack(2,"男","M","女","F"));

-- 方式二:子查询
with tmp as (
    select stack(2,"男","M","女","F")
) select * from tmp;

-- 方式三:永久视图
create view forever_view as
select stack(2,"男","M","女","F");

select * from forever_view;

-- 方式四:临时视图
create temporary view tmp_view as
select stack(2,"男","M","女","F");

select * from tmp_view;

-- 方式五:创建表
create table tb as
select stack(2,"男","M","女","F");

select * from tb;

-- 缓存表:类似Spark Core中的缓存,提高数据分析效率
cache table cache_tb as
select stack(2,"男","M","女","F");

-- 查询缓存表
select * from cache_tb;

-- 清理指定缓存
uncache table cache_tb;

select * from cache_tb;

-- 清空所有的缓存
clear cache;

四. 窗口函数

格式:
分析函数 over(partition by xxx order by xxx [asc|desc] [rows between xxx and xxx])

分析函数的分类:
1- 第一类: 排序函数。row_number() rank() dense_rank() ntile()

1、都是用来编号的
2、如果出现了重复(针对order by中的字段内容)数据
2.1- row_number:不管有没有重复,从1开始依次递增进行编号
2.2- rank():如果数据重复,编号相同,并且会占用后续的编号
2.3- dense_rank():如果数据重复,编号相同,但是不会占用后续的编号
2.4- ntile(n):将数据分为n个桶,不传入参数默认为1

2- 第二类: 聚合函数。sum() avg() count() max() min()…

1、可以通过窗口函数实现级联求各种值的操作。当后续遇到需要在计算的时候,将当前行或者之前之后的数据关联起来计算的情况,可以使用窗口函数。
2、如果没有排序字段,也就是没有order by语句,直接将窗口打开到最大,整个窗口内的数据全部被计算,不管执行到哪一行,都是针对整个窗口内的数据进行计算。
3、如果有排序字段,并且还存在重复数据的情况,默认会将重复范围内的数据放到一个窗口中计算
4、可以通过rows between xxx and xxx来限定窗口的统计数据范围
4.1- unbounded preceding: 从窗口的最开始
4.2- N preceding: 当前行的前N行,例如1 preceding、2 preceding
4.3- current row: 当前行
4.4- unbounded following: 到窗口的最末尾
4.5- N following: 当前行的后N行,例如1 following、2 following

3- 第三类: 取值函数。lead() lag() first_value() last_value()

-- 准备数据
create temporary view t1 (cookie,datestr,pv) as
values
           ('cookie1','2018-04-10',1),
            ('cookie1','2018-04-11',5),
            ('cookie1','2018-04-12',7),
            ('cookie1','2018-04-13',3),
            ('cookie1','2018-04-14',2),
            ('cookie1','2018-04-15',4),
            ('cookie1','2018-04-16',4),
            ('cookie2','2018-04-10',2),
            ('cookie2','2018-04-11',3),
            ('cookie2','2018-04-12',5),
            ('cookie2','2018-04-13',6),
            ('cookie2','2018-04-14',3),
            ('cookie2','2018-04-15',9),
            ('cookie2','2018-04-16',7);

select * from t1;
-- 1- 第一类: 排序函数。row_number() rank() dense_rank() ntile()
select
    cookie,pv,
    row_number() over (partition by cookie order by pv desc) as rs1,
    rank() over (partition by cookie order by pv desc) as rs2,
    dense_rank() over (partition by cookie order by pv desc) as rs3,
    ntile() over (partition by cookie order by pv desc) as rs4
from t1;
-- 2- 第二类: 聚合函数。sum() avg() count() max() min()...
select
    cookie,pv,
    -- 一次性直接将窗口打开到最大
    sum(pv) over(partition by cookie) as rs1,
    -- 依次慢慢打开窗口,如果数据相同,直接放到同一个窗口中
    sum(pv) over(partition by cookie order by pv) as rs2,
    -- 依次慢慢打开窗口,限定窗口的统计范围从窗口的最开始到当前行
    sum(pv) over(partition by cookie order by pv rows between unbounded preceding and current row) as rs3,
    -- 以当前行为中心,往前推一行。也就是从上一行计算到当前行
    sum(pv) over(partition by cookie order by pv rows between 1 preceding and current row ) as rs4,
    -- 从窗口的最开始一直统计到窗口的最终结尾
    sum(pv) over(partition by cookie order by pv rows between unbounded preceding and unbounded following) as rs5,
    -- 从当前行统计到窗口的结尾
    sum(pv) over(partition by cookie order by pv rows between current row and unbounded following) as rs6,
    -- 以当前行为中心,统计上一行、当前行、下一行总共3行的数据
    sum(pv) over(partition by cookie order by pv rows between 1 preceding and 1 following) as rs7,
    sum(pv) over(partition by cookie order by pv rows between 2 preceding and 3 following) as rs8
from t1;

-- 3- 第三类: 取值函数。lead() lag() first_value() last_value()
select
    cookie,pv,
    -- 默认取下一行数据
    lead(pv) over(partition by cookie order by pv) as rs1,
    -- 默认取上一行数据
    lag(pv) over(partition by cookie order by pv) as rs2,
    -- 默认取窗口内的第一条数据
    first_value(pv) over(partition by cookie order by pv) as rs3,
    -- 默认取窗口内的最后一条数据
    last_value(pv) over(partition by cookie order by pv) as rs4
from t1;

五. 横向迭代

/*
需求: 已知 c1列数据, 计算出 c2 和 c3列数据
c2 = c1+2
c3=c1*(c2+3)
 */
-- 数据准备
select explode(sequence(1,3));
select stack(3,1,2,3);

-- 方式一:子查询
-- 计算c2
with t1 as (
    select explode(sequence(1,3)) as c1
)select c1,(c1+2) as c2 from t1;
-- 计算c3
with t1 as (
    select explode(sequence(1,3)) as c1
)
select c1,c2,c1*(c2+3) as c3 from
(select c1,(c1+2) as c2 from t1);

-- 方式二:视图方式
-- 准备数据
create temporary view view_t1 as
select explode(sequence(1,3)) as c1;

select * from view_t1;
-- 计算c2并创建视图
create temporary view view_t2 as
select c1,(c1+2) as c2 from view_t1;

select * from view_t2;
-- 计算c3并创建视图
create temporary view view_t3 as
select c1,c2,c1*(c2+3) as c3 from view_t2;

select * from view_t3;

六. 纵向迭代

需求: 计算 c4:

计算逻辑: 当c2=1 , 则 c4=1 ; 否则 c4 = (上一个c4 + 当前的c3)/2
在这里插入图片描述

-- 数据准备
create temporary view view_data (c1,c2,c3)
as values
(1,1,6),
(1,2,23),
(1,3,8),
(1,4,4),
(1,5,10),
(2,1,23),
(2,2,14),
(2,3,17),
(2,4,20);

select * from view_data;

方式一:创建临时视图继续计算c4的值,对于练习阶段数据量小还行,即使是数量小,也有很多重复代码,所以对于以后海量数据的计算,这种方法显然是不合理的。

--方式一:
-- 步骤一:当c2=1 , 则 c4=1
create temporary view col_tmp1 as
select c1,c2,c3,if(c2=1,1,null)as c4 from view_data;

select * from col_tmp1;

-- 步骤二:否则 c4 = (上一个c4 +  当前的c3)/2
create temporary view col_tmp2 as
select
c1,c2,c3,
if(c2=1,1,((lag(c4) over (partition by c1 order by c2))+c3)/2) as c4
from col_tmp1;

select * from col_tmp2;

create temporary view col_tmp3 as
select
c1,c2,c3,
if(c2=1,1,((lag(c4) over (partition by c1 order by c2))+c3)/2) as c4
from col_tmp2;

select * from col_tmp3;

create temporary view col_tmp4 as
select
c1,c2,c3,
if(c2=1,1,((lag(c4) over (partition by c1 order by c2))+c3)/2) as c4
from col_tmp3;

select * from col_tmp4;

create temporary view col_tmp5 as
select
c1,c2,c3,
if(c2=1,1,((lag(c4) over (partition by c1 order by c2))+c3)/2) as c4
from col_tmp4;

select * from col_tmp5;

方式二:基于pandas进行自定义聚合函数(UDAF)操作

#!/usr/bin/env python
# @desc : 
__coding__ = "utf-8"
__author__ = "bytedance"

import pyspark.sql.functions as F
import pandas as pd
import os
from pyspark.sql import SparkSession
from pyspark.sql.types import FloatType

os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'

if __name__ == '__main__':
    # 1- 创建SparkSession对象
    spark = SparkSession.builder\
        .config('spark.sql.shuffle.partitions',1)\
        .appName('sparksql_udaf')\
        .master('local[*]')\
        .getOrCreate()

    # 2- 数据输入
    spark.sql("""
        create temporary view view_data (c1,c2,c3)
        as values
        (1,1,6),
        (1,2,23),
        (1,3,8),
        (1,4,4),
        (1,5,10),
        (2,1,23),
        (2,2,14),
        (2,3,17),
        (2,4,20)
    """)

    # 3- 数据处理
    # 3.1- 当c2=1 , 则 c4=1
    spark.sql("""
        create temporary view heng_tmp_1 as
        select
            c1,c2,c3,if(c2=1,1,null) as c4
        from view_data
    """)

    spark.sql("""
        select * from heng_tmp_1
    """).show()

    # 3.2- 否则 c4 = (上一个c4 +  当前的c3)/2
    # 3.2.1- 基于Pandas实现UDAF函数,创建自定义的Python函数
    # 3.2.2- 注册进SparkSQL中
    # @F.pandas_udf(returnType=FloatType())
    @F.pandas_udf(returnType="float")
    def c4_udaf_func(c3:pd.Series, c4:pd.Series) -> float:
        print(f"{c3}")
        print(f"{c4}")

        tmp_c4 = None

        for i in range(0,len(c3)):
            if i==0:
                tmp_c4 = c4[i] # c4[0]
            else:
                tmp_c4 = (tmp_c4 + c3[i]) / 2

        return tmp_c4

    spark.udf.register("c4_udaf",c4_udaf_func)

    spark.sql("""
        select 
            c1,c2,c3,
            c4_udaf(c3,c4) over(partition by c1 order by c2) as c4
        from heng_tmp_1
    """).show()

    # 4- 数据输出
    # 5- 释放资源
    spark.stop()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用githubDesktop部署静态页面到github

准备项目 现在桌面新建文件夹 在githubDesktop选择新建存储库,本地路径选择新建的文件夹路径 选择发布到存储库,将本地文件夹的内容和github进行连接 将项目文件复制粘贴到新建的文件夹里面 在githubDesktop填写摘要和描述,选择上传 …

一文教你如何本地搭建Qchan图床网站实现公网远程访问

文章目录 前言1. Qchan网站搭建1.1 Qchan下载和安装1.2 Qchan网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar云端设置2.2 Cpolar本地设置 3. 公网访问测试总结 前言 图床作为云存储的一项重要应用场景,在大量开发人员的努力下,已经开发出大…

【Java 数据结构】对象的比较

Java中对象的比较 1. PriorityQueue中插入对象2. 元素的比较2.1 基本类型的比较2.2 对象比较的问题 3. 对象的比较3.1 覆写基类的equals3.2 基于Comparble接口类的比较3.3 基于比较器比较3.4 三种方式对比 4. 集合框架中PriorityQueue的比较方式5. 使用PriorityQueue创建大小堆…

Vue学习笔记(二)快速入门

Vue学习笔记&#xff08;二&#xff09;快速入门 vue小试牛刀 hello-vue3.html <body><div id"app"><h1>{{msg}}</h1></div><script type"module">import {createApp} from https://unpkg.com/vue3/dist/vue.esm-b…

【MySQL】——用SQL语句实现数据库和基本表的创建

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

【数据库】mysql触发器使用

题目&#xff1a; 创建职工表以及职工工资表职工表字段&#xff1a;工号&#xff0c;姓名&#xff0c;性别&#xff0c;年龄工资表字段&#xff1a;编号自增&#xff0c;职工工号&#xff0c;基础工资10000通过触发器实现&#xff1a;对职工进行添加时 工资表中也要体现当前职…

【Linux】环境基础开发工具的使用(一)

前言&#xff1a;在此之前我们学习了一些Linux的权限&#xff0c;今天我们进一步学习Linux下开发工具的使用。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:Linux的深度刨析 &#x1f448; &#x1f4af;代码仓库:卫卫周大胖的学习日记…

docker下,容器无法启动,要删除里面的文件

第一步&#xff1a;进入docker cd /var/lib/docker 第二步&#xff1a;查找&#xff0c;我这里是拼音分词器 find ./ -name py 第三步&#xff1a;得到路径 第四步&#xff1a;删除或复制或移动&#xff0c;我这里是删除py文件夹 rm -rf ./over那一串 第五步&#xff1a;想干…

在 python 中调用 C/C++

Python 是一种很好用的胶水语言&#xff0c;利用Python的简洁和C的高效&#xff0c;基本可以解决99%的问题了&#xff0c;剩下那 1% 的问题也就不是问题了&#xff0c;毕竟不是所有问题都可解。 一般的&#xff0c;Python和C的交互分为这两种情况&#xff1a; 用C扩展Python&…

转转基于MQ的分布式重试框架设计方案

文章目录 1 背景2 方案3 效果4 可选项5 注意事项6 总结 1 背景 在分布式场景下&#xff0c;为了保障系统的可用性和数据的最终一致性&#xff0c;采用基于消息队列&#xff08;MQ&#xff09;的重试机制是一种常见的解决方案。伪代码如下&#xff1a; /*** 需要保证最终一致性…

数据可视化Tableau

目录 一.第一次实验课内容 1、熟悉Tableau Desktop的工作环境。 2、熟悉数据导入、维度和度量的区分以及不同数据字段类型的标识符。 3、熟悉工作表的基本操作&#xff0c;主要包括行列功能区&#xff0c;标记卡&#xff0c;筛选器&#xff0c;智能推荐的使用。 4、作业--…

3. Mybatis的XML配置文件(重点)

目录 1 Mybatis的XML配置文件 1.1 XML配置文件规范 1.2 XML配置文件实现 1.3 MybatisX的使用 2. Mybatis动态SQL 2.1 什么是动态SQL 2.2 动态SQL-if 2.2.1 条件查询 2.2.2更新 2.3 动态SQL-foreach 2.4 动态SQL-sql&include 1.mybatis入门 2.mybatis基本操作 1…

六大效果图渲染技巧,实现照片级真实感!

追求完美的3D艺术家们&#xff0c;注意了&#xff01;掌握这六大效果图渲染技巧&#xff0c;就能令你的作品逾越虚拟与现实的边界。无需长篇大论&#xff0c;立即提升你的渲染工作至照片级别的真实感&#xff01;让观者难以分辨&#xff0c;这正是我们所追求的魔法。 六大效果图…

LRU缓存(Leetcode146)

例题&#xff1a; 分析&#xff1a; 题目要求函数get和put要达到O(1)的时间复杂度&#xff0c;可以用 hashMap 来实现&#xff0c;因为要满足逐出最久未使用的元素的一个效果&#xff0c;还需要配合一个双向链表来共同实现。链表中的节点为一组key-value。 我们可以用双向链表来…

LED显示屏安装后常见调试问题及解决方法

LED全彩显示屏在户外广泛应用&#xff0c;通常由多个箱体组装而成。在安装和调试过程中&#xff0c;可能会出现一些常见问题&#xff0c;下面对这些问题及解决方法进行汇总&#xff1a; 1. 加载不上可能是哪些原因造成的&#xff1f; - A. 确保控制系统硬件已正确上电&#xff…

RK3588平台开发系列讲解(视频篇)H.264码流结构介绍

文章目录 一、 码流查看工具二、 I帧、 P帧、 B帧三、序列四、GOP, 即关键帧间隔五、片和宏块沉淀、分享、成长,让自己和他人都能有所收获!😄 📢H.264码流结构介绍。 一、 码流查看工具 ① H.264码流查看工具: Elecard_streamEye、 Elecard StreamEye Tools、 Special…

本地部署Tomcat开源服务器并结合内网穿透远程访问

文章目录 前言1.本地Tomcat网页搭建1.1 Tomcat安装1.2 配置环境变量1.3 环境配置1.4 Tomcat运行测试1.5 Cpolar安装和注册 2.本地网页发布2.1.Cpolar云端设置2.2 Cpolar本地设置 3.公网访问测试4.结语 前言 Tomcat作为一个轻量级的服务器&#xff0c;不仅名字很有趣&#xff0…

智能小车案例:基于Raspberry Pi的自动巡航与避障系统

项目背景 随着物联网技术的不断发展&#xff0c;智能小车成为了现代生活和工业自动化中的重要工具。为了实现智能小车的自动巡航与避障功能&#xff0c;我们采用了Raspberry Pi作为主控制器&#xff0c;结合传感器和执行器&#xff0c;构建了一个完整的系统。 所需材料 Raspber…

山海鲸可视化:引领银行管理进入数据可视化新时代

在金融领域&#xff0c;数据是决策的关键。作为山海鲸可视化的开发者&#xff0c;我们深知数据的价值&#xff0c;并致力于通过可视化技术为银行管理提供更为直观、高效的数据分析工具。 应用场景&#xff1a; 风险管理&#xff1a;银行在运营过程中面临各种风险&#xff0c;如…

第17次修改了可删除可持久保存的前端html备忘录:增加年月日星期,增加倒计时,更改保存区名称可以多个备忘录保存不一样的信息,匹配背景主题:现代深色

第17次修改了可删除可持久保存的前端html备忘录&#xff1a;增加年月日星期&#xff0c;增加倒计时&#xff0c;更改保存区名称可以多个备忘录保存不一样的信息&#xff0c;匹配背景主题&#xff1a;现代深色 备忘录代码&#xff1a; <!DOCTYPE html> <html lang&quo…