我的编程空间,编程开发者的网络收藏夹
学习永远不晚

带你快速了解SQL窗口函数

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

带你快速了解SQL窗口函数

窗口函数形如:

表达式 OVER (PARTITION BY 分组字段 ORDER BY 排序字段)

有两个能力:

  • 当表达式为 rank() dense_rank() row_number() 时,拥有分组排序能力。
  • 当表达式为 sum() 等聚合函数时,拥有累计聚合能力。

无论何种能力,窗口函数都不会影响数据行数,而是将计算平摊在每一行。

这两种能力需要区分理解。

底表

以上是示例底表,共有 8 条数据,城市1、城市2 两个城市,下面各有地区1~4,每条数据都有该数据的人口数。

分组排序

如果按照人口排序,ORDER BY people 就行了,但如果我们想在城市内排序怎么办?

此时就要用到窗口函数的分组排序能力:

SELECT *, rank() over (PARTITION BY city ORDER BY people) FROM test

该 SQL 表示在 city 组内按照 people 进行排序。

其实 PARTITION BY 也是可选的,如果我们忽略它:

SELECT *, rank() over (ORDER BY people) FROM test

也是生效的,但该语句与普通 ORDER BY 等价,因此利用窗口函数进行分组排序时,一般都会使用 PARTITION BY。

各分组排序函数的差异

我们将 rank() dense_rank() row_number() 的结果都打印出来:

SELECT *, 
rank() over (PARTITION BY city ORDER BY people),
dense_rank() over (PARTITION BY city ORDER BY people),
row_number() over (PARTITION BY city ORDER BY people)
FROM test

其实从结果就可以猜到,这三个函数在处理排序遇到相同值时,对排名统计逻辑有如下差异:

  • rank(): 值相同时排名相同,但占用排名数字。
  • dense_rank(): 值相同时排名相同,但不占用排名数字,整体排名更加紧凑。
  • row_number(): 无论值是否相同,都强制按照行号展示排名。

上面的例子可以优化一下,因为所有窗口逻辑都是相同的,我们可以利用 WINDOW AS 提取为一个变量:

SELECT *, 
rank() over wd, dense_rank() over wd, row_number() over wd
FROM test
WINDOW wd as (PARTITION BY city ORDER BY people)

累计聚合

我们之前说过,凡事使用了聚合函数,都会让查询变成聚合模式。如果不用 GROUP BY,聚合后返回行数会压缩为一行,即使用了 GROUP BY,返回的行数一般也会大大减少,因为分组聚合了。

然而使用窗口函数的聚合却不会导致返回行数减少,那么这种聚合是怎么计算的呢?我们不如直接看下面的例子:

SELECT *, 
sum(people) over (PARTITION BY city ORDER BY people)
FROM test

可以看到,在每个 city 分组内,按照 people 排序后进行了 累加(相同的值会合并在一起),这就是 BI 工具一般说的 RUNNGIN_SUM 的实现思路,当然一般我们排序规则使用绝对不会重复的日期,所以不会遇到第一个红框中合并计算的问题。

累计函数还有 avg() min() 等等,这些都一样可以作用于窗口函数,其逻辑可以按照下图理解:

你可能有疑问,直接 sum(上一行结果,下一行) 不是更方便吗?为了验证猜想,我们试试 avg() 的结果:

可见,如果直接利用上一行结果的缓存,那么 avg 结果必然是不准确的,所以窗口累计聚合是每行重新计算的。当然也不排除对于 sum、max、min 做额外性能优化的可能性,但 avg 只能每行重头计算。

与 GROUP BY 组合使用

窗口函数是可以与 GROUP BY 组合使用的,遵循的规则是,窗口范围对后面的查询结果生效,所以其实并不关心是否进行了 GROUP BY。我们看下面的例子:

按照地区分组后进行累加聚合,是对 GROUP BY 后的数据行粒度进行的,而不是之前的明细行。

总结

窗口函数在计算组内排序或累计 GVM 等场景非常有用,我们只要牢记两个知识点就行了:

  • 分组排序要结合 PARTITION BY 才有意义。
  • 累计聚合作用于查询结果行粒度,支持所有聚合函数。

讨论地址是:精读《SQL 窗口函数》· Issue #405 · ascoders/weekly

到此这篇关于SQL窗口函数的文章就介绍到这了,更多相关SQL窗口函数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

带你快速了解SQL窗口函数

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

一文带你快速理解JavaScript中call()函数的使用

这篇文章主要为大家详细介绍了JavaScript中call()函数的使用的相关知识,文中的示例代码讲解详细,具有一定的学习价值,需要的可以参考一下
2023-03-23

一文带你了解JS箭头函数

本文可以让你了解所有有关JavaScript箭头函数的信息。我们将告诉你如何使用ES6的箭头语法,以及在代码中使用箭头函数时需要注意的一些常见错误。你会看到很多例子来说明它们是如何工作的。
2022-11-22

一文带你快速了解C/C++标准库中的ptrdiff_t

ptrdiff_t是C/C++标准库中定义的一个与机器相关的数据类型,ptrdiff_t类型变量通常用来保存两个指针减法操作的结果,下面这篇文章主要给大家介绍了关于C/C++标准库中ptrdiff_t的相关资料,需要的朋友可以参考下
2022-11-16

万字长文带你快速了解整个Flutter开发流程

文章目录 背景1.简介与优势Flutter是什么?为什么选Flutter? 2.开发环境搭建安装Flutter SDK配置开发环境 3.创建项目项目结构概览: 4.UI 构建与布局什么是Widget:StatelessW
2023-08-24

一文带你了解JavaScript函数柯里化

柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。本文将通过一些示例带大家深入了解JS的函数柯里化,需要的可以参考一下
2023-02-01

都2023年了,Servlet还有必要学习吗?一文带你快速了解Servlet

文章目录 1. 前言2. Servlet 简介3. 快速入门4. 执行流程5. 生命周期6. 方法初识7. 体系结构8. urlPattern 配置9. XML配置10. 总结 1. 前言 起初,所有的 Web 网站都是静态的,
2023-08-17

一篇文章带你了解Python递归函数

递归是一种常见的编程技巧,在Python中也可以通过递归函数来实现。递归函数是指在函数的定义中调用函数本身的情况。通过递归函数,我们可以解决一些需要重复执行相同操作的问题。首先,让我们来看一个简单的例子,计算一个数的阶乘。阶乘是指从1到该数
2023-09-22

一文带你快速了解JS正则表达式的使用方法

JavaScript中如何使用正则表达式?下面本篇文章带大家深入了解一下JavaScript正则表达式的使用方法,希望对大家有所帮助!
2023-05-14

一文带你了解Java中的函数式编程

函数式编程的理论基础是阿隆佐·丘奇(AlonzoChurch)于1930年代提出的λ演算(LambdaCalculus)。这篇文章主要为大家介绍了函数式编程的相关知识,希望对大家有所帮助
2023-05-14

深入了解NumPy函数的快速入门指南

快速上手NumPy函数:详细介绍,需要具体代码示例引言:NumPy是Python中常用的数值计算库之一,它提供了高效的多维数组(ndarray)对象和强大的函数库,让我们能够快速有效地进行数值计算和数据处理。本文将详细介绍NumPy中常用
深入了解NumPy函数的快速入门指南
2024-01-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录