学习SQL【4】-聚合与排序

《学习SQL【4】-聚合与排序》 学习.png

随着表中记录(数据行)的不断积累,存储数据逐渐增加,有时我们可能希望计算出这些数据的合计值或者平均值等,这个时候就需要使用SQL语句的汇总操作等方法。

一:对表进行聚合排序

1:聚合函数

通过SQL对数据进行某种操作或计算时需要使用函数。SQL有五种常用的函数:
● COUNT:计算表中数据的行数(记录数)。
● SUM:计算表中数值列中数据的合计数。
● AVG:计算表中数值列中数据的平均值。
● MAX:计算表中数值列中数据的最大值。
● MIN:计算表中数值列中数据的最小值。

如上所示,用于汇总的函数成为聚合函数或者聚集函数。接下来,我们仍然使用之前创建的Product表进行函数的学习,Product表的结构和内容如下:

 product_id | product_name | product_type | sale_price | purchase_price | regist_date------------+--------------+--------------+------------+----------------+-------------
 0001       | T衫          | 衣服         |       1000 |            500 | 2017-09-20
 0002       | 打孔器       | 办公用品     |        500 |            320 | 2017-09-11
 0003       | 运动T衫      | 衣服         |       4000 |           2800 |
 0004       | 菜刀         | 厨房用具     |       3000 |           2800 | 2017-09-20
 0005       | 高压锅       | 厨房用具     |       6800 |           5000 | 2017-01-15
 0006       | 叉子         | 厨房用具     |        500 |                | 2017-09-20
 0007       | 擦菜板       | 厨房用具     |        880 |            790 | 2016-04-28
 0008       | 圆珠笔       | 办公用品     |        100 |                | 2017-11-11
(8 行记录)

2:计算表中数据的行数

使用COUNT函数时,输入表的列,就能输出数据行数:
例如,计算全部数据的行数:

 SELECT COUNT(*)         
      FROM Product;

执行结果:

 count-------
     8
(1 行记录)

COUNT()中的星号,代表全部列的意思。函数的输入值称为参数,输出值称为返回值。

3:计算NULL之外的数据的行数

SELECT COUNT(purchase_price)       
     FROM Product;

执行结果:

 count-------
     6
(1 行记录)

对于COUNT函数来说,参数列不同,计算结果也会不同。COUNT(*)会得到包含NULL的数据行数,而COUNT(<列名>)会得到NULL之外的数据行数。

4:计算合计值

计算合计值需要使用SUM函数
例,计算销售单价的合计值:

SELECT SUM(sale_price)       
     FROM Product;

执行结果:

  sum-------
 16780
(1 行记录)

例如,计算销售单价和进货单价的合计值:

SELECT SUM(sale_price), SUM(purchase_price)       
     FROM Product;

执行结果:

  sum  |  sum-------+-------
 16780 | 12210
(1 行记录)

注释:

聚合函数会将NULL排除在外,但COUNT(*)例外,并不会排除NULL。

5:计算平均值

计算平均值需要使用AVG函数
例,计算销售单价的平均值:

 SELECT AVG(sale_price)         
      FROM Product;

执行结果:

          avg-----------------------
 2097.5000000000000000
(1 行记录)

例如,计算销售单价和进货单价的平均值:

 SELECT AVG(sale_price), AVG(purchase_price)         
      FROM Product;

执行结果:

          avg          |          avg-----------------------+-----------------------
 2097.5000000000000000 | 2035.0000000000000000
(1 行记录)

6:计算最大值和最小值

想要计算出多条记录的最大值或最小值,可以分别使用MAX和MIN函数。
例,计算销售单价的最大值和进货单价的最小值:

SELECT MAX(sale_price), MIN(purchase_price)       
     FROM Product;

执行结果:

 max  | min------+-----
 6800 | 320
(1 行记录)

例如,计算登记日期的最大值和最小值:

SELECT MAX(regist_date), MIN(regist_date)       
     FROM Product;

执行结果:

   max     |    min------------+------------
 2017-11-11 | 2016-04-28
(1 行记录)

MAX/MIN函数几乎适用于所有数据类型的列。而SUM/AVG函数只适用于数值类型的列。

7:使用聚合函数删除重复值(关键字DISTINCT)

例,计算除去重复数据后的数据行数:

SELECT COUNT(DISTINCT product_type)       
     FROM Product;

执行结果:

 count-------
     3
(1 行记录)

想要计算值的种类时,可以在COUNT函数的参数中使用DISTINCT。
在聚合函数的参数中使用DISTINCT,可以删除重复数据。

二:对表进行分组

1:GROUP BY子句

使用GROUP BY子句可以像切蛋糕那样将表分割。GROUP BY子句的语法结构如下:

SELECT <列名1>, <列名2>,...       
     FROM <表名>   
  GROUP BY <列名1>, <列名2>,...;

例如,按照商品种类统计数据行数:

SELECT product_type, COUNT(*)       
     FROM Product   
  GROUP BY product_type;

执行结果:

 product_type | count--------------+-------
 衣服         |     2
 办公用品     |     2
 厨房用具     |     4
(3 行记录)

● 在GROUP BY 子句中指定的列称为聚合键。
● 子句的书写顺序(暂定):
SELECT→FROM→ WHERE→ GROUP BY
● SQL子句的顺序不能更改,也不能相互替换。

2:聚合键中包含NULL的情况

例,按照进货单价统计数据行数:

SELECT purchase_price, COUNT(*)       
     FROM Product   
  GROUP BY purchase_price;

执行结果:

 purchase_price | count----------------+-------
                |     2
            320 |     1
            500 |     1
           5000 |     1
           2800 |     2
            790 |     1
(6 行记录)

聚合键中包含NULL时,在结果中会以“不确定”行(空行)的形式显示出来。

3:使用WHERE子句和GROUP BY 子句的执行结果

例,同时使用WHERE子句和GROUP BY子句:

SELECT purchase_price, COUNT(*)       
     FROM Product   
  WHERE product_type = '衣服'
  GROUP BY purchase_price;

执行结果:

 purchase_price | count----------------+-------
            500 |     1
           2800 |     1
(2 行记录)

4:与聚合函数和GROUP BY 子句有关的常见错误

● 使用GROUP BY 子句时,SELECT 子句中不能出现聚合键之外的列名。
● 在GROUP BY 子句中不能使用SELECT子句中定义的别名。
● GROUP BY 子句结果的显示是无序的。
● 只有SLEECT子句、GROUP BY 子句和HAVING子句中能够使用聚合函数,WHERE 子句中不能使用聚合函数。

三:为聚合结果指定条件

1:HAVING子句

对集合指定条件可以使用HAVING子句。HAVING子句的语法如下:

SELECT <列名1>, <列名2>,...      
     FROM <表名>   
  GROUP BY <列名1>, <列名2>,...   
  HAVING <分组结果对应的条件>;

注释:

HAVING子句要写在GROUP BY 子句之后。
例,从按照商品种类进行分组后的结果中,取出“包含的数据行数为2行”的组:

SELECT product_type, COUNT(*)       
     FROM Product   
  GROUP BY product_type   
  HAVING COUNT(*) = 2;

执行结果:

product_type | count--------------+-------
 衣服         |     2
 办公用品     |     2
(2 行记录)

不使用HAVING子句的情况

SELECT product_type, COUNT(*)       
     FROM Product   
  GROUP BY product_type;

执行结果:

product_type | count--------------+-------
 衣服         |     2
 办公用品     |     2
 厨房用具     |     4
(3 行记录)

2:HAVING子句的构成要素

HAVING子句中能够使用的3中要素如下:
● 常数
● 聚合函数
● GROUP BY 子句中 指定的列名(聚合键)

3:相比于HAVING子句,更适合于写在WHERE子句中的条件

我们会发现,有些条件既可以写在HAVING子句中,也可以写在WHERE 子句中,而且结果是一样的。这些条件就是聚合键所对应的条件。
例,将条件写在HAVING 子句中:

SELECT product_type, COUNT(*)      
     FROM Product   
  GROUP BY product_type   
  HAVING product_type = '衣服';

执行结果:

product_type | count--------------+-------
 衣服         |     2
(1 行记录)

将条件书写在WHERE子句中的情况

SELECT product_type, COUNT(*)       
     FROM Product   
  WHERE product_type = '衣服'
  GROUP BY product_type;

执行结果:

 product_type | count--------------+-------
 衣服         |     2
(1 行记录)

两者结果完全相同,但是,从执行速度来讲,将条件写在WHERE 子句中要比写在HAVING子句中的处理速度要快。所以,聚合键所对应的条件应该书写在WHERE 子句中。

四:对查询结果进行排序

1:ORDER BY子句

使用ORDER BY 子句可对查询结果进行排序,ORDER BY子句的语法:

SELECT <列名1>, <列名2>,...      
     FROM <表名>   
  ORDER BY <排列基准1>, <排列基准2>,....;

例,按照销售单价由低到高(升序)进行排序:

SELECT product_id, product_name, sale_price, purchase_price        
    FROM Product   
    ORDER BY sale_price;

执行结果:

 product_id | product_name | sale_price | purchase_price------------+--------------+------------+----------------
 0008       | 圆珠笔       |        100 |
 0006       | 叉子         |        500 |
 0002       | 打孔器       |        500 |            320
 0007       | 擦菜板       |        880 |            790
 0001       | T衫          |       1000 |            500
 0004       | 菜刀         |       3000 |           2800
 0003       | 运动T衫      |       4000 |           2800
 0005       | 高压锅       |       6800 |           5000
(8 行记录)

● ORDER BY子句中书写的列名称为排序键。
● ORDER BY 子句通常写在SELECT语句的末尾。

2:指定升序或降序

降序排列时,可使用DESC关键字。
例,按照销售单价由高到低(降序)进行排序:

SELECT product_id, product_name, sale_price, purchase_price      
    FROM Product   
  ORDER BY sale_price DESC;

执行结果:

 product_id | product_name | sale_price | purchase_price------------+--------------+------------+----------------
 0005       | 高压锅       |       6800 |           5000
 0003       | 运动T衫      |       4000 |           2800
 0004       | 菜刀         |       3000 |           2800
 0001       | T衫          |       1000 |            500
 0007       | 擦菜板       |        880 |            790
 0002       | 打孔器       |        500 |            320
 0006       | 叉子         |        500 |
 0008       | 圆珠笔       |        100 |
(8 行记录)

注释:

未指定ORDER BY 子句中排列顺序时会默认以升序排列。

3:指定多个排序键

可以在ORDER BY 子句中指定多个排序键,规则是优先使用左侧的键,如果该列存在相同的值,再接着参考右侧的键。
例,按照销售单价和商品编号的升序进行排序:

SELECT product_id, product_name, sale_price, purchase_price      
     FROM Product   
  ORDER BY sale_price, product_id;

执行结果:

product_id | product_name | sale_price | purchase_price------------+--------------+------------+----------------
 0008       | 圆珠笔       |        100 |
 0002       | 打孔器       |        500 |            320
 0006       | 叉子         |        500 |
 0007       | 擦菜板       |        880 |            790
 0001       | T衫          |       1000 |            500
 0004       | 菜刀         |       3000 |           2800
 0003       | 运动T衫      |       4000 |           2800
 0005       | 高压锅       |       6800 |           5000
(8 行记录)

4:NULL 的排序

例,按照进货单价的升序进行排序:

SELECT product_id, product_name, sale_price, purchase_price         
    FROM Product   
  ORDER BY purchase_price;

执行结果:

product_id | product_name | sale_price | purchase_price------------+--------------+------------+----------------
 0002       | 打孔器       |        500 |            320
 0001       | T衫          |       1000 |            500
 0007       | 擦菜板       |        880 |            790
 0003       | 运动T衫      |       4000 |           2800
 0004       | 菜刀         |       3000 |           2800
 0005       | 高压锅       |       6800 |           5000
 0006       | 叉子         |        500 |
 0008       | 圆珠笔       |        100 |
(8 行记录)

如上所示,排序键包含NULL时,会在开头或者末尾进行汇总。

5:几点关于ORDER BY子句的事项

● 在ORDER BY 子句中可以使用SELECT子句中定义的别名。
● 在ORDER BY 子句中可以使用SLEECT子句中为使用的列和聚合函数。
● 在ORDER BY 子句中不要使用列编号。

路漫漫其修远兮,吾将上下而求索。

每天学习一点点,每天进步一点点。

    原文作者:爱吃西瓜的番茄酱
    原文地址: https://www.jianshu.com/p/707afeecd84f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞