当前位置: 代码迷 >> 综合 >> datawhale-sql打卡之Task 5:SQL高级处理
  详细解决方案

datawhale-sql打卡之Task 5:SQL高级处理

热度:35   发布时间:2023-12-18 04:47:44.0

目录

  • 1 什么是窗口函数?
  • 2 窗口函数种类
    • 2.1 专用窗口函数
      • RANK函数
      • DENSE_RANK函数
      • ROW_NUMBER函数
    • 2.2 将聚合函数用于窗口函数
    • 2.3 窗口函数的的应用 - 计算移动平均
  • 3 GROUPING运算符
  • 练习题

1 什么是窗口函数?

窗口函数也称为OLAP函数,即online analyticall processing

常规的SELECT语句都是对整张表进行查询 而窗口函数可以让我们有选择的去某一部分数据进行汇总、计算和排序

<窗口函数> OVER ([PARTITION BY <列名>]ORDER BY <排序用列名>)  
- []中的内容可以省略
  • PARTITON BY是用来分组,类似于GROUP BY 子句的分组功能,即选择要看哪个窗口,但是它并不具备GROUP BY 子句的汇总功能,并不会改变原始表中记录的行数
  • ORDER BY是用来排序,即决定窗口内是按哪一列(字段)哪种规则(升序降序)排列的
SELECT product_name,product_type,sale_price,RANK() OVER (PARTITION BY product_typeORDER BY sale_price) AS ranking
FROM product;

在这里插入图片描述
去掉PARTITION BY看一下

SELECT product_name,product_type,sale_price,RANK() OVER (ORDER BY sale_price) AS ranking
FROM product;

在这里插入图片描述
通过对比可以看到,窗口函数其实就是首先执行PARTITION BY对原数据分组,然后对组内数据按照ORDER BY排序,然后对数据挨个应用窗口函数。如果没有PARTITION BY,就是整个原数据是一组。

  • 应用sum其实是从头到尾累加
SELECT product_id,product_name,sale_price,SUM(sale_price) OVER (ORDER BY sale_price) AS current_sum
FROM product;

在这里插入图片描述

2 窗口函数种类

窗口函数可以分为两类,

  • 一是 将SUM、MAX、MIN等聚合函数用在窗口函数中

  • 二是 RANK、DENSE_RANK、ROW_NUMBER等排序用的专用窗口函数

2.1 专用窗口函数

RANK函数

计算排序时,如果存在相同位次的记录,则会跳过之后的位次

例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、4 位……

DENSE_RANK函数

计算排序时,即使存在相同位次的记录,也不会跳过之后的位次。

例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、2 位……

ROW_NUMBER函数

计算排序时,赋予唯一的连续位次。

例)有 3 条记录排在第 1 位时:1 位、2 位、3 位、4 位

SELECT product_name,product_type,sale_price,RANK() OVER (ORDER BY sale_price) as ranking,DENSE_RANK() OVER (ORDER BY sale_price) as dense_ranking,ROW_NUMBER() OVER (ORDER BY sale_price) as row_ranking
FROM product;

在这里插入图片描述

2.2 将聚合函数用于窗口函数

聚合函数在窗口函数中的使用方法和之前的专用窗口函数一样,只是出来的结果是一个累计的聚合函数值。

SELECT product_name,product_type,sale_price,sum(sale_price) OVER (ORDER BY sale_price) as current_sum,avg(sale_price) OVER (ORDER BY sale_price) as current_avg
FROM product;

聚合函数结果是,按我们指定的排序,当前所在行及之前所有的行的合计或均值。即累计到当前行的聚合
在这里插入图片描述
注意到,这里由于叉子和打孔器价格一样都是500,导致累加时,对用于打孔器和叉子的累加和累加求平均都是一样的,且都是算了2次500的结果。

2.3 窗口函数的的应用 - 计算移动平均

聚合函数在窗口函数使用时,计算的是累积到当前行的所有的数据的聚合。 实际上,还可以指定更加详细的汇总范围。该汇总范围称为框架(frame)。

<窗口函数> OVER (ORDER BY <排序用列名>ROWS n PRECEDING )  <窗口函数> OVER (ORDER BY <排序用列名>ROWS BETWEEN n PRECEDING AND n FOLLOWING)

PRECEDING(“之前”), 将frame指定为 “截止到之前 n 行”,加上自身行
FOLLOWING(“之后”), 将frame指定为 “截止到之后 n 行”,加上自身行

SELECT  product_name,product_type,sale_price,SUM(sale_price) OVER (ORDER BY sale_price ROWS 2 PRECEDING) as moving_sum,AVG(sale_price) OVER (ORDER BY sale_price ROWS 2 PRECEDING) as moving_avg
FROM product;

在这里插入图片描述

SELECT  product_name,product_type,sale_price,AVG(sale_price) OVER (ORDER BY sale_price ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) as moving_avg1,AVG(sale_price) OVER (ORDER BY sale_price ROWS 2 PRECEDING) as moving_avg
FROM product;

在这里插入图片描述

3 GROUPING运算符

常规的GROUP BY 只能得到每个分类的小计,有时候还需要计算分类的合计,可以用 ROLLUP关键字。

SELECT  product_type,regist_date,SUM(sale_price) AS sum_priceFROM productGROUP BY product_type, regist_date WITH ROLLUP 

在这里插入图片描述在这里插入图片描述
ROLLUP 对product_type, regist_date两列进行合计汇总。结果实际上有三层聚合,如上图 模块3是常规的 GROUP BY 的结果,需要注意的是衣服 有个注册日期为空的,这是本来数据就存在日期为空的,不是对衣服类别的合计; 模块2和1是 ROLLUP 带来的合计,模块2是对产品种类的合计,模块1是对全部数据的总计

练习题

  • 5.1
    在这里插入图片描述
    执行结果是,current_max_price列是根据product_id排序的结果找出的基于本行和前面所有行的最大价格
  • 5.2
    继续使用product表,计算出按照登记日期(regist_date)升序进行排列的各日期的销售单价(sale_price)的总额。排序是需要将登记日期为NULL 的“运动 T 恤”记录排在第 1 位(也就是将其看作比其他日期都早)
SELECT  product_name,regist_date,sale_price,SUM(sale_price) OVER (ORDER BY regist_date) AS sum_priceFROM product;

在这里插入图片描述

  • 5.3
    思考题

① 窗口函数不指定PARTITION BY的效果是什么?

不指定PARTITION BY时,就是全体数据是一组

② 为什么说窗口函数只能在SELECT子句中使用?实际上,在ORDER BY 子句使用系统并不会报错。

窗口函数就是在order by基础上做的进一步运算,所以直接order by 即可


Task 5:SQL高级处理

  相关解决方案