LabHub
学习 学习路径 课程

SQL 实战

用窗口函数算出排名与趋势

在 LabHub 中继续学习

目标

使用 row_number、rank、dense_rank、累计和、lag、占比、ntile 计算排名和趋势,并判断何时使用窗口函数。

为什么重要

聚合会折叠行并丢失单行信息,但许多问题需要在保留每行时引用周边数据。窗口函数正好解决这一问题。自连接和相关子查询也能实现,但代码更长且要多次读表。

请记住:窗口函数结果不能用于同一个 SELECT 的 WHERE。 WHERE 在处理顺序中更早执行,因此按排名筛选时必须再套一层子查询或 CTE。

步骤

  1. 商品按类别内价格降序排列,并在并列时按 id 升序,为该序号创建视图 v_ranked_products。列为 categoryidpricern
  2. 创建视图 v_rank_compare,用两种方式对全部商品按价格降序排名。列为 idpricernkdrnk
  3. 创建视图 v_running_revenue,保存月度销售额与累计额。列为 monthrevenuecum_revenue,月份基准为 AT TIME ZONE 'Asia/Seoul'
  4. 创建视图 v_mom。列为 monthrevenueprev_revenuediff,首月 prev_revenue 为空。
  5. 创建视图 v_channel_share。列为 channelrevenueshare_pct,比例保留两位且合计 100。
  6. 创建视图 v_top3_per_category,列为 categoryidprice
  7. 商品按价格升序排列,并列时按 id 升序,将其四等分后创建视图 v_price_quartile。列为 idpricequartile
  8. 创建视图 v_first_order,列为 customer_idorder_idordered_at;时间相同时,以 id 较小者为首单。

参考

按类别标记价格序号

商品按类别内价格降序排列,并在并列时按 id 升序,为该序号创建视图 v_ranked_products。列为 categoryidpricern

同时使用划分窗口的子句和确定窗口内部顺序的子句。并列时用 id 区分。

比较两种排名函数

创建视图 v_rank_compare,用两种方式对全部商品按价格降序排名。列为 idpricernk(并列后跳号)、drnk(不跳号)。

有一个函数会在并列后跳过名次,另一个不会。

计算累计销售额

创建视图 v_running_revenue,保存已完成订单的月度销售额和累计销售额。列为 monthrevenuecum_revenue,月份基准为 AT TIME ZONE 'Asia/Seoul'

先生成月度汇总,再在其结果上打开窗口。顺序相反会把聚合与窗口混在一起。

计算环比增减

创建视图 v_mom,在相同月度汇总上增加上月销售额和增减值。列为 monthrevenueprev_revenuediff,第一个月的 prev_revenue 必须为空。

有一个函数可以获取上一行的值。第一个月没有前值,因此应为空。

计算占总额比例

创建视图 v_channel_share,保存各渠道销售额及其占总额比例。列为 channelrevenueshare_pct,比例四舍五入到小数点后两位,合计应为 100。

OVER 括号留空时,整个结果集是一个窗口,无需运行两次查询。

选出每组前 3 名

创建视图 v_top3_per_category,保存每个类别价格最高的 3 个商品。列为 categoryidprice

窗口函数结果不能用于同一个 SELECT 的 WHERE,必须再套一层。

划分价格四分位组

商品按价格升序排列,并列时按 id 升序,将其四等分后创建视图 v_price_quartile。列为 idpricequartile

有一个函数可以把行等分为 n 组并编号。请准确设置排序条件。

查找每位客户的第一张订单

创建视图 v_first_order,保存每位客户的第一张订单。列为 customer_idorder_idordered_at;时间相同时,以 id 较小的订单为第一张。

按客户为订单依时间编号,只保留第一条。没有订单的客户不应出现。