【数据库】SQL高级处理:窗口函数,GROUPING

8.1 窗口函数
8.1 根据不同的种类,销售单价由高到低排列RANK

postgres=# SELECT product_name,product_type,sale_price,
postgres-# RANK () OVER (PARTITION BY product_type
postgres(# ORDER BY sale_price) AS ranking
postgres-# FROM Product;
 product_name | product_type | sale_price | ranking
--------------+--------------+------------+---------
 圆珠笔       | 办公用品     |        100 |       1
 打孔器       | 办公用品     |        500 |       2
 叉子         | 厨房用具     |        500 |       1
 擦菜板       | 厨房用具     |        880 |       2
 菜刀         | 厨房用具     |       3000 |       3
 高压锅       | 厨房用具     |       6800 |       4
 T恤          | 衣服         |       1000 |       1
 运动T恤      | 衣服         |       4000 |       2
(8 行记录)

8.3 使用RANK,DENSE_RANK或ROW_NUMBER排序的区别

postgres=# SELECT product_name,product_type,sale_price,
postgres-# RANK () OVER (ORDER BY sale_price) AS ranking,
postgres-# DENSE_RANK () OVER (ORDER BY sale_price) AS dense_ranking,
postgres-# ROW_NUMBER () OVER (ORDER BY sale_price) AS row_ranking
postgres-# FROM Product;
 product_name | product_type | sale_price | ranking | dense_ranking | row_ranking
--------------+--------------+------------+---------+---------------+-------------
 圆珠笔       | 办公用品     |        100 |       1 |             1 |           1
 叉子         | 厨房用具     |        500 |       2 |             2 |           2
 打孔器       | 办公用品     |        500 |       2 |             2 |           3
 擦菜板       | 厨房用具     |        880 |       4 |             3 |           4
 T恤          | 衣服         |       1000 |       5 |             4 |           5
 菜刀         | 厨房用具     |       3000 |       6 |             5 |           6
 运动T恤      | 衣服         |       4000 |       7 |             6 |           7
 高压锅       | 厨房用具     |       6800 |       8 |             7 |           8
(8 行记录)

注:窗口函数的使用位置:SELECT子句当中
8.4 SUM作为窗口函数

postgres=# SELECT product_id,product_name,sale_price,
postgres-# SUM (sale_price) OVER (ORDER BY product_id) AS current_sum
postgres-# FROM Product;
 product_id | product_name | sale_price | current_sum
------------+--------------+------------+-------------
 0001       | T恤          |       1000 |        1000
 0002       | 打孔器       |        500 |        1500
 0003       | 运动T恤      |       4000 |        5500
 0004       | 菜刀         |       3000 |        8500
 0005       | 高压锅       |       6800 |       15300
 0006       | 叉子         |        500 |       15800
 0007       | 擦菜板       |        880 |       16680
 0008       | 圆珠笔       |        100 |       16780
(8 行记录)

8.5 AVG 函数作为窗口函数

postgres=# SELECT product_id,product_name,sale_price,
postgres-# AVG(sale_price) OVER (ORDER BY product_id) AS avg_price
postgres-# FROM Product;
 product_id | product_name | sale_price |       avg_price
------------+--------------+------------+-----------------------
 0001       | T恤          |       1000 | 1000.0000000000000000
 0002       | 打孔器       |        500 |  750.0000000000000000
 0003       | 运动T恤      |       4000 | 1833.3333333333333333
 0004       | 菜刀         |       3000 | 2125.0000000000000000
 0005       | 高压锅       |       6800 | 3060.0000000000000000
 0006       | 叉子         |        500 | 2633.3333333333333333
 0007       | 擦菜板       |        880 | 2382.8571428571428571
 0008       | 圆珠笔       |        100 | 2097.5000000000000000
(8 行记录)

8.6 指定最靠近3行作为汇总对象

postgres=# SELECT product_id,product_name,sale_price,
postgres-# AVG(sale_price) OVER (ORDER BY product_id
postgres(# ROWS 2 PRECEDING) AS avg_p2
postgres-# FROM Product;
 product_id | product_name | sale_price |        avg_p2
------------+--------------+------------+-----------------------
 0001       | T恤          |       1000 | 1000.0000000000000000
 0002       | 打孔器       |        500 |  750.0000000000000000
 0003       | 运动T恤      |       4000 | 1833.3333333333333333
 0004       | 菜刀         |       3000 | 2500.0000000000000000
 0005       | 高压锅       |       6800 | 4600.0000000000000000
 0006       | 叉子         |        500 | 3433.3333333333333333
 0007       | 擦菜板       |        880 | 2726.6666666666666667
 0008       | 圆珠笔       |        100 |  493.3333333333333333
(8 行记录)

8.7 将当前记录的前后作为汇总对象

postgres=# SELECT product_id,product_name,sale_price,
postgres-# AVG(sale_price) OVER (ORDER BY product_id
postgres(# ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) AS avg_3
postgres-# FROM Product;
 product_id | product_name | sale_price |         avg_3
------------+--------------+------------+-----------------------
 0001       | T恤          |       1000 |  750.0000000000000000
 0002       | 打孔器       |        500 | 1833.3333333333333333
 0003       | 运动T恤      |       4000 | 2500.0000000000000000
 0004       | 菜刀         |       3000 | 4600.0000000000000000
 0005       | 高压锅       |       6800 | 3433.3333333333333333
 0006       | 叉子         |        500 | 2726.6666666666666667
 0007       | 擦菜板       |        880 |  493.3333333333333333
 0008       | 圆珠笔       |        100 |  490.0000000000000000
(8 行记录)

8.8 想要结果是按照ranking的顺序,还得使用ORDER BY在语句末尾

postgres=# SELECT product_id,product_name,sale_price,
postgres-# RANK () OVER (ORDER BY sale_price) AS ranking
postgres-# FROM Product
postgres-# ORDER BY ranking;
 product_id | product_name | sale_price | ranking
------------+--------------+------------+---------
 0008       | 圆珠笔       |        100 |       1
 0006       | 叉子         |        500 |       2
 0002       | 打孔器       |        500 |       2
 0007       | 擦菜板       |        880 |       4
 0001       | T恤          |       1000 |       5
 0004       | 菜刀         |       3000 |       6
 0003       | 运动T恤      |       4000 |       7
 0005       | 高压锅       |       6800 |       8
(8 行记录)

8.11 UNION ALL连接汇总行和小结

postgres=# SELECT '合计' AS product_type,SUM(sale_price)
postgres-# FROM Product
postgres-# UNION ALL
postgres-# SELECT product_type,SUM(sale_price)
postgres-# FROM Product
postgres-# GROUP BY product_type;
 product_type |  sum
--------------+-------
 合计         | 16780
 衣服         |  5000
 办公用品     |   600
 厨房用具     | 11180
(4 行记录)

GROUPING :ROLLUP,CUBE,GROUPING SETS
8.12 使用ROLLUP同时得出合计和小计

postgres=# SELECT product_type,SUM(sale_price) AS sum_price
postgres-# FROM product
postgres-# GROUP BY ROLLUP (product_type);
 product_type | sum_price
--------------+-----------
 办公用品     |       600
 厨房用具     |     11180
 衣服         |      5000
              |     16780
(4 行记录)

8.14 在GROUP中添加登记日期

postgres=# SELECT product_type, regist_date, SUM(sale_price) AS sum_price
postgres-#   FROM Product
postgres-#  GROUP BY ROLLUP(product_type,regist_date);
 product_type | regist_date | sum_price
--------------+-------------+-----------
 办公用品     | 2009-09-11  |       500
 办公用品     | 2009-11-11  |       100
 办公用品     |             |       600
 厨房用具     | 2008-04-28  |       880
 厨房用具     | 2009-01-15  |      6800
 厨房用具     | 2009-09-20  |      3500
 厨房用具     |             |     11180
 衣服         | 2009-09-20  |      1000
 衣服         |             |      4000
 衣服         |             |      5000
              |             |     16780
(11 行记录)

8.15 用GROUPING 判断是否为NULL

postgres=# SELECT GROUPING(product_type) AS product_type,
postgres-# GROUPING(regist_date) AS regist_date,SUM(sale_price) AS sum_price
postgres-# FROM Product
postgres-# GROUP BY ROLLUP(product_type,regist_date);
 product_type | regist_date | sum_price
--------------+-------------+-----------
            0 |           0 |       500
            0 |           0 |       100
            0 |           1 |       600
            0 |           0 |       880
            0 |           0 |      6800
            0 |           0 |      3500
            0 |           1 |     11180
            0 |           0 |      1000
            0 |           0 |      4000
            0 |           1 |      5000
            1 |           1 |     16780
(11 行记录)

8.16 在超级分组记录中插入需要的字符串

postgres=# SELECT CASE WHEN GROUPING(product_type) = 1
postgres-#             THEN '商品种类 合计'
postgres-#             ELSE product_type END AS product_type,
postgres-#        CASE WHEN GROUPING(regist_date) = 1
postgres-# THEN '登记日期 合计'
postgres-#  ELSE CAST(regist_date AS VARCHAR(16)) END AS regist_date,
postgres-#        SUM(sale_price) AS sum_price
postgres-#   FROM Product
postgres-#  GROUP BY ROLLUP(product_type, regist_date);
 product_type  |  regist_date  | sum_price
---------------+---------------+-----------
 办公用品      | 2009-09-11    |       500
 办公用品      | 2009-11-11    |       100
 办公用品      | 登记日期 合计 |       600
 厨房用具      | 2008-04-28    |       880
 厨房用具      | 2009-01-15    |      6800
 厨房用具      | 2009-09-20    |      3500
 厨房用具      | 登记日期 合计 |     11180
 衣服          | 2009-09-20    |      1000
 衣服          |               |      4000
 衣服          | 登记日期 合计 |      5000
 商品种类 合计 | 登记日期 合计 |     16780

8.17 使用CUBE代替ROLLUP取得全部组合的结果

postgres=# SELECT CASE WHEN GROUPING(product_type) = 1
postgres-#             THEN '商品种类 合计'
postgres-#             ELSE product_type END AS product_type,
postgres-#        CASE WHEN GROUPING(regist_date) = 1
postgres-#             THEN '登记日期 合计'
postgres-#             ELSE CAST(regist_date AS VARCHAR(16)) END AS regist_date,
postgres-#        SUM(sale_price) AS sum_price
postgres-#   FROM Product
postgres-# GROUP BY CUBE(product_type,regist_date);
 product_type  |  regist_date  | sum_price
---------------+---------------+-----------
 办公用品      | 2009-09-11    |       500
 办公用品      | 2009-11-11    |       100
 办公用品      | 登记日期 合计 |       600
 厨房用具      | 2008-04-28    |       880
 厨房用具      | 2009-01-15    |      6800
 厨房用具      | 2009-09-20    |      3500
 厨房用具      | 登记日期 合计 |     11180
 衣服          | 2009-09-20    |      1000
 衣服          |               |      4000
 衣服          | 登记日期 合计 |      5000
 商品种类 合计 | 登记日期 合计 |     16780
 商品种类 合计 | 2008-04-28    |       880
 商品种类 合计 | 2009-01-15    |      6800
 商品种类 合计 | 2009-09-11    |       500
 商品种类 合计 | 2009-09-20    |      4500
 商品种类 合计 | 2009-11-11    |       100
 商品种类 合计 |               |      4000
(17 行记录)

8.18 使用GROUPING SETS取得部分组合的结果

postgres=# SELECT CASE WHEN GROUPING(product_type) = 1
postgres-#             THEN '商品种类 合计'
postgres-#             ELSE product_type END AS product_type,
postgres-#        CASE WHEN GROUPING(regist_date) = 1
postgres-#             THEN '登记日期 合计'
postgres-#             ELSE CAST(regist_date AS VARCHAR(16)) END AS regist_date,
postgres-#        SUM(sale_price) AS sum_tanka
postgres-#   FROM Product
postgres-#  GROUP BY GROUPING SETS (product_type, regist_date);
 product_type  |  regist_date  | sum_tanka
---------------+---------------+-----------
 办公用品      | 登记日期 合计 |       600
 厨房用具      | 登记日期 合计 |     11180
 衣服          | 登记日期 合计 |      5000
 商品种类 合计 | 2008-04-28    |       880
 商品种类 合计 | 2009-01-15    |      6800
 商品种类 合计 | 2009-09-11    |       500
 商品种类 合计 | 2009-09-20    |      4500
 商品种类 合计 | 2009-11-11    |       100
 商品种类 合计 |               |      4000
(9 行记录)

练习:
在这里插入图片描述

postgres=# SELECT regist_date,product_name,sale_price,
postgres-# SUM(sale_price) OVER(ORDER BY regist_date NULLS FIRST) AS sum_sale_price
postgres-# FROM Product;
 regist_date | product_name | sale_price | sum_sale_price
-------------+--------------+------------+----------------
             | 运动T恤      |       4000 |           4000
 2008-04-28  | 擦菜板       |        880 |           4880
 2009-01-15  | 高压锅       |       6800 |          11680
 2009-09-11  | 打孔器       |        500 |          12180
 2009-09-20  | T恤          |       1000 |          16680
 2009-09-20  | 菜刀         |       3000 |          16680
 2009-09-20  | 叉子         |        500 |          16680
 2009-11-11  | 圆珠笔       |        100 |          16780
(8 行记录)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQL Server窗口函数是一种用于进行分组或分区计算的函数。它可以与聚合函数或排序函数结合使用。窗口函数SQL Server中被用于实现OLAP(在线分析处理)功能,并且可以对数据库中的数据进行实时分析处理窗口函数的分类包括能够作为窗口函数的聚合函数(如SUM、AVG、COUNT、MAX、MIN)以及专用窗口函数(如RANK、DENSE_RANK、ROW_NUMBER)。这些函数可以根据指定的分组或分区对数据进行计算,并返回结果。因此,SQL Server窗口函数在数据分析和报表制作中起着重要的作用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [SQL Sever 学习笔记十一——窗口函数GROUPING运算符](https://blog.csdn.net/weixin_45666566/article/details/106407762)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [SQL SERVER中的开窗函数](https://blog.csdn.net/sinat_25172701/article/details/48084511)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值