当前位置:   article > 正文

SQL函数-窗口函数-聚合窗口函数_sum窗口函数

sum窗口函数

许多常见的聚合函数也可以作为窗口函数使用,包括AVG(),SUM(),COUNT(),MAX()以及MIN()等函数.

一、移动聚合

1、移动平均值

AVG函数在作为窗口函数使用时,可以用于计算随着当前移动的窗口内数据行的平均值。

例如,查找不同产品每个月以及截至当前月最近3个月的平均销售额

  1. SELECT m.product,m.ym,m.amount,
  2. AVG(m.amount) OVER(
  3. PARTITION BY m.product
  4. ORDER BY m.ym
  5. ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
  6. )
  7. FROM sales_monthly m
  8. ORDER BY m.product,m.ym

AVG函数OVER子句中的PARTITION BY选项表示按照产品进行分区。

ORDER BY选项表示按照月份进行排序;ROWS BETWEEN 2 PRECEDING AND CURRENT ROW表示窗口从当前行的前2行开始,直到当前行结束。

执行结果如下:

对于桔子:

第一个月的分析窗口只有1行数据,因此平均销售额为“10154”。

第二个月的分析窗口为第1行和第2行,因此平均销售额为(10154+10183)/2=10168.5.

第三个月的分析窗口为第1行到第3行的数据,因此平均销售额为(10154+10183+10245)/3=10194。

第四个月的分析窗口为第2行到第4行的数据,因此平均销售额为(10183+10245+10325)/3=10251。

依此类推,直到计算完“桔子”所有月份的平均销售额,然后开始计算其他产品的平均销售额。

2、移动求和

在移动窗口内除了可以求平均值之外,也可以进行移动求和

例如,查找不同产品每个月以及截至当前月最近3个月的累计销售额

  1. SELECT m.product,m.ym,m.amount,
  2. SUM(m.amount) OVER(
  3. PARTITION BY m.product
  4. ORDER BY m.ym
  5. ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
  6. )
  7. FROM sales_monthly m
  8. ORDER BY m.product,m.ym;

SUM函数OVER子句中的PARTITION BY选项表示按照产品进行分区。

ORDER BY选项表示按照月份进行排序;ROWS BETWEEN 2 PRECEDING AND CURRENT ROW表示窗口从当前行的前2行开始,直到当前行结束。

查询结果如下:

对于桔子:

第一个月的分析窗口只有1行数据,因此平均销售额为“10154”。

第二个月的分析窗口为第1行和第2行,因此平均销售额为10154+10183=20337.

第三个月的分析窗口为第1行到第3行的数据,因此平均销售额为10154+10183+10245=30582。

第四个月的分析窗口为第2行到第4行的数据,因此平均销售额为10183+10245+10325=30753。

依此类推,直到计算完“桔子”所有月份的近3个月累计销售额,然后开始计算其他产品的近3个月累计销售额。

除了AVG()、SUM() 之外,其他的聚合函数也可以在移动窗口中计算。

二、累计聚合

1、累计求和

SUM函数作为窗口函数时,可以用于统计指定窗口内的累计值。

例如:查找不同产品截至当前月份的累计销售额:

  1. SELECT m.product,m.ym,m.amount,
  2. SUM(m.amount) OVER(
  3. PARTITION BY m.product
  4. ORDER BY m.ym
  5. ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  6. )
  7. FROM sales_monthly m
  8. ORDER BY m.product,m.ym;

SUM函数OVER子句中的PARTITION BY选项表示按照产品进行分区。

ORDER BY选项表示按照月份进行排序。

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW表示窗口从当前分区第1行开始,直到当前行结束。

查询结果如下:

对于桔子:

第一个月的分析窗口只有1行数据,因此累计销售额为“10154”。

第二个月的分析窗口为第1行和第2行,因此累计销售额为10154+10183=20337.

第三个月的分析窗口为第1行到第3行的数据,因此累计销售额为10154+10183+10245=30582。

第四个月的分析窗口为第1行到第4行的数据,因此平均销售额为10154+10183+10245+10325=40907。

依此类推,直到计算完“桔子”所有月份的累计销售额,然后开始计算其他产品的累计销售额。

2、累计平均值

例如:查找不同产品截至当前月份的平均销售额:

  1. SELECT m.product,m.ym,m.amount,
  2. AVG(m.amount) OVER(
  3. PARTITION BY m.product
  4. ORDER BY m.ym
  5. ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  6. )
  7. FROM sales_monthly m
  8. ORDER BY m.product,m.ym;

执行结果如下:

对于桔子:

第一个月的分析窗口只有1行数据,因此累计销售额为“10154”。

第二个月的分析窗口为第1行和第2行,因此累计销售额为(10154+10183)/2=10168.5.

第三个月的分析窗口为第1行到第3行的数据,因此累计销售额为(10154+10183+10245)/3=10194。

第四个月的分析窗口为第1行到第4行的数据,因此平均销售额为(10154+10183+10245+10325)/4=10226.75。

依此类推,直到计算完“桔子”所有月份的累计平均值,然后开始计算其他产品的累计平均值。

除了AVG()、SUM() 之外,其他的聚合函数也可以在聚合窗口中计算。

三、ORDER BY的默认设置

对于聚合窗口函数,如果我们没有指定ORDER BY选项,默认的窗口大小就是整个分区。如果我们指定了ORDER BY选项,默认的窗口大小就是分区的第一行到当前行。

1、指定ORDER BY选项

因此累计求和的案例中,在指定了ORDER BY选项后,ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT NOW选项可以省略。

省略后的语句为:

  1. SELECT m.product,m.ym,m.amount,
  2. SUM(m.amount) OVER(
  3. PARTITION BY m.product
  4. ORDER BY m.ym
  5. ## ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  6. )
  7. FROM sales_monthly m
  8. ORDER BY m.product,m.ym;

执行结果与下面语法执行结果相同。

  1. SELECT m.product,m.ym,m.amount,
  2. SUM(m.amount) OVER(
  3. PARTITION BY m.product
  4. ORDER BY m.ym
  5. ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  6. )
  7. FROM sales_monthly m
  8. ORDER BY m.product,m.ym;

2、不指定ORDER BY 选项

如果去掉ORDER BY选项,查询的窗口大小就是整个分区

语法如下:

  1. SELECT m.product,m.ym,m.amount,
  2. SUM(m.amount) OVER(
  3. PARTITION BY m.product
  4. ## ORDER BY m.ym
  5. ## ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  6. )
  7. FROM sales_monthly m
  8. ORDER BY m.product,m.ym;

执行结果如下:这时,合计值就变成了分区内所有记录的合计。

四、RANGE指定窗口

除使用ROWS关键字以数据行为单位指定窗口的偏移量外,我们也可以使用RANGE关键字以数值为单位指定窗口的偏移量。

例如:查询短期之内(5天)累计转账超过100万元的账户

  1. SELECT a.log_ts,a.from_user,a.total_amount FROM (
  2. SELECT log_ts,t.from_user,t.amount,
  3. SUM(t.amount) OVER(
  4. PARTITION BY t.from_user
  5. ORDER BY t.log_ts
  6. RANGE INTERVAL '5' DAY PRECEDING
  7. ) AS total_amount
  8. FROM transfer_log t
  9. WHERE t.type = '转账'
  10. ) a
  11. WHERE total_amount >= 1000000;

执行结果如下:


举例使用数据:

1、sales_monthly表:表中存储了不同产品(苹果、香蕉、橘子)每个月的销售额情况。

  1. ##创建销量表sales_monthly
  2. ##product表示产品名称,ym表示年月,amount表示销售金额(元)
  3. CREATE TABLE sales_monthly(product VARCHAR(20), ym VARCHAR(10), amount NUMERIC(10, 2));
  4. ##生成测试数据
  5. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201801',10159.00);
  6. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201802',10211.00);
  7. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201803',10247.00);
  8. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201804',10376.00);
  9. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201805',10400.00);
  10. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201806',10565.00);
  11. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201807',10613.00);
  12. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201808',10696.00);
  13. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201809',10751.00);
  14. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201810',10842.00);
  15. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201811',10900.00);
  16. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201812',10972.00);
  17. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201901',11155.00);
  18. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201902',11202.00);
  19. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201903',11260.00);
  20. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201904',11341.00);
  21. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201905',11459.00);
  22. INSERT INTO sales_monthly (product,ym,amount) VALUES ('苹果','201906',11560.00);
  23. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201801',10138.00);
  24. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201802',10194.00);
  25. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201803',10328.00);
  26. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201804',10322.00);
  27. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201805',10481.00);
  28. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201806',10502.00);
  29. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201807',10589.00);
  30. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201808',10681.00);
  31. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201809',10798.00);
  32. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201810',10829.00);
  33. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201811',10913.00);
  34. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201812',11056.00);
  35. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201901',11161.00);
  36. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201902',11173.00);
  37. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201903',11288.00);
  38. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201904',11408.00);
  39. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201905',11469.00);
  40. INSERT INTO sales_monthly (product,ym,amount) VALUES ('香蕉','201906',11528.00);
  41. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201801',10154.00);
  42. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201802',10183.00);
  43. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201803',10245.00);
  44. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201804',10325.00);
  45. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201805',10465.00);
  46. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201806',10505.00);
  47. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201807',10578.00);
  48. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201808',10680.00);
  49. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201809',10788.00);
  50. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201810',10838.00);
  51. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201811',10942.00);
  52. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201812',10988.00);
  53. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201901',11099.00);
  54. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201902',11181.00);
  55. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201903',11302.00);
  56. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201904',11327.00);
  57. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201905',11423.00);
  58. INSERT INTO sales_monthly (product,ym,amount) VALUES ('桔子','201906',11524.00);

2、transfer_log表:表中记录了一些银行账户的交易日志。

  1. ## 创建银行交易日志表transfer_log
  2. ## Oracle、MySQL、PostgreSQL以及SQLite
  3. CREATE TABLE transfer_log
  4. ( log_id INTEGER NOT NULL PRIMARY KEY, -- 交易日志编号
  5. log_ts TIMESTAMP NOT NULL, -- 交易时间
  6. from_user VARCHAR(50) NOT NULL, -- 交易发起账号
  7. to_user VARCHAR(50), -- 交易接收账号
  8. type VARCHAR(10) NOT NULL, -- 交易类型
  9. amount NUMERIC(10) NOT NULL -- 交易金额(元)
  10. );
  11. ## 生成测试数据
  12. ## Oracle 需要执行以下ALTER语句
  13. ## ALTER SESSION SET nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS';
  14. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (1,'2021-01-02 10:31:40','62221234567890',NULL,'存款',50000);
  15. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (2,'2021-01-02 10:32:15','62221234567890',NULL,'存款',100000);
  16. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (3,'2021-01-03 08:14:29','62221234567890','62226666666666','转账',200000);
  17. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (4,'2021-01-05 13:55:38','62221234567890','62226666666666','转账',150000);
  18. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (5,'2021-01-07 20:00:31','62221234567890','62227777777777','转账',300000);
  19. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (6,'2021-01-09 17:28:07','62221234567890','62227777777777','转账',500000);
  20. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (7,'2021-01-10 07:46:02','62221234567890','62227777777777','转账',100000);
  21. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (8,'2021-01-11 09:36:53','62221234567890',NULL,'存款',40000);
  22. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (9,'2021-01-12 07:10:01','62221234567890','62228888888881','转账',10000);
  23. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (10,'2021-01-12 07:11:12','62221234567890','62228888888882','转账',8000);
  24. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (11,'2021-01-12 07:12:36','62221234567890','62228888888883','转账',5000);
  25. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (12,'2021-01-12 07:13:55','62221234567890','62228888888884','转账',6000);
  26. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (13,'2021-01-12 07:14:24','62221234567890','62228888888885','转账',7000);
  27. INSERT INTO transfer_log (log_id,log_ts,from_user,to_user,type,amount) VALUES (14,'2021-01-21 12:11:16','62221234567890','62228888888885','转账',70000);
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/894262
推荐阅读
相关标签
  

闽ICP备14008679号