ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

SQL基础-第8章 SQL高级处理

2021-11-19 16:02:03  阅读:166  来源: 互联网

标签:product Product 处理 price 高级 sale SQL type SELECT


8-1 窗口函数

什么是窗口函数

OLAP 是 OnLine Analytical Processing 的简称,意思是对数据库数据进行实时分析处理。
窗口函数也称为 OLAP 函数

窗口函数的语法

<窗口函数> OVER ([PARTITION BY <列清单>]
ORDER BY <排序用列清单>)

能够作为窗口函数使用的函数

  • 能够作为窗口函数的聚合函数( SUM、 AVG、 COUNT、 MAX、 MIN)
  • ANK、 DENSE_RANK、 ROW_NUMBER 等专用窗口函数

语法的基本使用方法——使用RANK函数

窗口函数兼具分组和排序两种功能。
通过PARTITION BY分组后的记录集合称为“窗口”

-- 根据不同的商品种类,按照销售单价从低到高的顺序创建排序表
SELECT product_name, product_type, sale_price,
RANK () OVER (PARTITION BY product_type
ORDER BY sale_price) AS ranking
FROM Product;

无需指定PARTITION-BY

-- 不指定PARTITION BY
SELECT product_name, product_type, sale_price,
RANK () OVER (ORDER BY sale_price) AS ranking
FROM Product;

-- 比较RANK、 DENSE_RANK、 ROW_NUMBER的结果
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_num
FROM Product;

专用窗口函数的种类

  • RANK函数
    • 计算排序时,如果存在相同位次的记录,则会跳过之后的位次。
    • 例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、4 位……
  • DENSE_RANK函数
    • 同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次。
    • 例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、2 位……
  • ROW_NUMBER函数
    • 赋予唯一的连续位次。
    • 例)有 3 条记录排在第 1 位时:1 位、2 位、3 位、4 位……

由于专用窗口函数无需参数,因此通常括号中都是空的

窗口函数的适用范围

原则上窗口函数只能在SELECT子句中使用

作为窗口函数使用的聚合函数

-- 将SUM函数作为窗口函数使用
SELECT product_id, product_name, sale_price,
SUM(sale_price) OVER (ORDER BY product_id) AS current_sum
FROM Product;

计算移动平均

-- 将AVG函数作为窗口函数使用
SELECT product_id, product_name, sale_price,
AVG(sale_price) OVER (ORDER BY product_id) AS current_avg
FROM Product;

-- 指定“最靠近的3行”作为汇总对象
SELECT product_id, product_name, sale_price,
AVG (sale_price) OVER (ORDER BY product_id
ROWS 2 PRECEDING) AS moving_avg
FROM Product;

-- 将当前记录的前后行作为汇总对象
SELECT product_id, product_name, sale_price,
AVG (sale_price) OVER (ORDER BY product_id
ROWS BETWEEN 1 PRECEDING AND
1 FOLLOWING) AS moving_avg
FROM Product;

两个ORDER-BY

将聚合函数作为窗口函数使用时,会以当前记录为基准来决定汇总对象的记录。

-- 无法保证如下SELECT语句的结果的排列顺序
SELECT product_name, product_type, sale_price,
RANK () OVER (ORDER BY sale_price) AS ranking
FROM Product;

8-2 GROUPING运算符

同时得到合计行

-- 使用GROUP BY无法得到合计行
SELECT product_type, SUM(sale_price)
FROM Product
GROUP BY product_type;

-- 分别计算出合计行和汇总结果再通过UNION ALL进行连接
SELECT '合计' AS product_type, SUM(sale_price)
FROM Product
UNION ALL
SELECT product_type, SUM(sale_price)
FROM Product
GROUP BY product_type;

ROLLUP——同时得出合计和小计

超级分组记录默认使用NULL作为聚合键。

-- 使用ROLLUP同时得出合计和小计
SELECT product_type, SUM(sale_price) AS sum_price
FROM Product
GROUP BY product_type WITH ROLLUP;

-- 在GROUP BY中添加“登记日期”(不使用ROLLUP)
SELECT product_type, regist_date, SUM(sale_price) AS sum_price
FROM Product
GROUP BY product_type, regist_date;

-- 在GROUP BY中添加“登记日期”(使用ROLLUP)
SELECT product_type, regist_date, SUM(sale_price) AS sum_price
FROM Product
GROUP BY product_type, regist_date WITH ROLLUP;

GROUPING函数——让NULL更加容易分辨

-- 使用GROUPING函数来判断NULL
SELECT GROUPING(product_type) AS product_type,
GROUPING(regist_date) AS regist_date, SUM(sale_price) AS sum_price
FROM Product
GROUP BY ROLLUP(product_type, regist_date);

使用GROUPING函数能够简单地分辨出原始数据中的NULL和超级分组记录中的NULL

-- 使用GROUPING函数来判断NULL
SELECT GROUPING(product_type) AS product_type,
GROUPING(regist_date) AS regist_date, SUM(sale_price) AS sum_price
FROM Product
GROUP BY product_type, regist_date WITH ROLLUP;

-- 在超级分组记录的键值中插入恰当的字符串
SELECT CASE WHEN GROUPING(product_type) = 1
THEN '商品种类 合计'
ELSE product_type END AS product_type,
CASE WHEN GROUPING(regist_date) = 1
THEN '登记日期 合计'
ELSE regist_date END AS regist_date,
SUM(sale_price) AS sum_price
FROM Product
GROUP BY product_type, regist_date WITH ROLLUP;

练习题

8.1 请说出针对本章中使用的 Product(商品)表执行如下 SELECT 语句所能得到的结果。

SELECT product_id, product_name, sale_price,
MAX(sale_price) OVER (ORDER BY product_id) AS  current_max_price
FROM Product;

本题中 SELECT 语句的含义是“按照商品编号(product_id)的升序进行排序,
计算出截至当前行的最高销售单价”。因此,在显示出最高销售单价的同时,窗口函
数的返回结果也会变化。

8.2 继续使用Product表,计算出按照登记日期( regist_date)升序进行排列的各日期的销售单价( sale_price)的总额。排序是需要将登记日期为 NULL 的“运动 T 恤”记录排在第 1 位(也就是将其看作比其他日期都早)。

①和②两种方法都可以实现。
① regist_date 为 NULL 时,显示“1 年 1 月 1 日”

SELECT regist_date, product_name, sale_price,
SUM(sale_price) 
OVER (ORDER BY COALESCE(regist_date, CAST('0001-01-01' AS DATE))) 
AS current_sum_price
FROM Product;

② regist_date 为 NULL 时,将该记录放在最前显示

SELECT regist_date, product_name, sale_price,
SUM(sale_price) 
OVER (order by IF(ISNULL(regist_date),0,1), regist_date) 
AS current_sum_price
FROM Product;

标签:product,Product,处理,price,高级,sale,SQL,type,SELECT
来源: https://www.cnblogs.com/szlsay/p/15577772.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有