1. 程式人生 > 實用技巧 >SQL:三 聚合與排序

SQL:三 聚合與排序

對錶進行聚合查詢

聚合函式

  • 通過 SQL 對資料進行某種操作或計算時需要使用函式。

  • 常用函式

    • COUNT: 計算表中的記錄數(行數)
    • SUM: 計算表中數值列中資料的合計值
    • AVG: 計算表中數值列中資料的平均值
    • MAX: 求出表中任意列中資料的最大值
    • MIN: 求出表中任意列中資料的最小值
  • 用於彙總的函式稱為聚合函式或者聚集函式

計算表中資料的行數

  • 執行結果包括值為 NULL 的行
-- 計算全部資料的行數 
SELECT COUNT(*)  
FROM Product;

計算NULL之外的資料的行數

  • 對於 COUNT 函式來說,引數列不同計 算的結果也會發生變化
  • COUNT函式的結果根據引數的不同而不同。COUNT(*)會得到包含NULL的資料 行數,而COUNT(<列名>)會得到NULL之外的資料行數。
-- 計算NULL之外的資料行數 
SELECT COUNT(purchase_price) 
FROM Product;

計算合計值

  • 對於 SUM函式來說,即使包含 NULL,也可以計算出合計值
  • 聚合函式會將NULL排除在外。但COUNT(*)例外,並不會排除NULL
-- 計算銷售單價的合計值 
SELECT SUM(sale_price) 
FROM Product;

計算平均值

  • 會事先刪除NULL 再進行計算,值的個數減少
-- 計算銷售單價和進貨單價的平均值 
SELECT AVG(sale_price), AVG(purchase_price) 
FROM Product;

計算最大值和最小值

  • SUM/ AVG函式只能對數值型別的列使用
  • MAX/MIN 函式原則上可以適用 於任何資料型別的列
-- 計算銷售單價的最大值和進貨單價的最小值 
SELECT MAX(sale_price), MIN(purchase_price) 
FROM Product;

使用聚合函式刪除重複值(關鍵字DISTINCT)

  • 這時 DISTINCT 必須寫在括號中。這是因為必須要在計算 行數之前刪除 product_type 列中的重複資料
  • 想要計算值的種類時,可以在COUNT函式的引數中使用DISTINCT。
  • 所有的聚合函式都可以使用DISTINCT
-- 計算去除重複資料後的資料行數 
SELECT COUNT(DISTINCT product_type) 
FROM Product;

-- 先計算資料行數再刪除重複資料的結果 
SELECT DISTINCT COUNT(product_type)  
FROM Product;

對錶進行分組

GROUP BY子句

-- 使用GROUP BY子句進行彙總
SELECT <列名1>, <列名2>, <列名3>, …… 
FROM <表名> 
GROUP BY <列名1>, <列名2>, <列名3>, ……;

-- 按照商品種類統計資料行數 
SELECT product_type, COUNT(*)  
FROM Product 
GROUP BY product_type;

  • 在 GROUP BY 子句中指定的列稱為聚合鍵或者分組列

  • GROUP BY 子句的書寫位置也有嚴格要求,一定要寫在 FROM 語句之後

  • 子句的書寫順序(暫定)

      1. SELECT → 2. FROM → 3. WHERE → 4. GROUP BY

聚合鍵中包含NULL的情況

  • 當聚合鍵中包含 NULL 時,也會將 NULL 作為一組特定的資料

使用WHERE子句時GROUP BY的執行結果

-- 使用WHERE子句和GROUP BY子句進行彙總處理
SELECT <列名1>, <列名2>, <列名3>, …… 
FROM <表名> 
WHERE 
GROUP BY <列名1>, <列名2>, <列名3>, ……;

-- 同時使用WHERE子句和GROUP BY子句 
SELECT purchase_price, COUNT(*)  
FROM Product 
WHERE product_type = '衣服' 
GROUP BY purchase_price;

  • GROUP BY 和WHERE 並用時,SELECT 語句的執行順序

    • FROM → WHERE → GROUP BY → SELECT

與聚合函式和GROUP BY子句有關的常見錯誤

  • 常見錯誤①:在SELECT子句中書寫了多餘的列

    • SELECT 子句中只能存在以下三種元素

      • 常數
      • 聚合函式
      • GROUP BY子句中指定的列名(也就是聚合鍵)
    • 常會出現的錯誤就是把聚合鍵之外的列名書寫在SELECT 子 句之中

    • 使用GROUP BY子句時,SELECT子句中不能出現聚合鍵之外的列名

    • -- 在SELECT子句中書寫聚合鍵之外的列名會發生錯誤 
      
      SELECT product_name, purchase_price, COUNT(*)  
      FROM Product 
      GROUP BY purchase_price;
      
      /* 列名product_name 並沒有包含在GROUP BY 子句當中。因此,該列名也不能書寫在 SELECT 子句之中  */

  • 常見錯誤②:在GROUP BY子句中寫了列的別名

    • SQL 語句在 DBMS 內部的執行順序造成的——SELECT 子句在GROUP BY 子句之後執行。 在執行 GROUP BY 子句時,SELECT 子句中定義的別名,DBMS 還並 不知道。
    • 在GROUP BY子句中不能使用SELECT子句中定義的別名。
    • -- GROUP BY子句中使用列的別名會引發錯誤 
      SELECT product_type AS pt, COUNT(*) 
      FROM Product 
      GROUP BY pt

  • 常見錯誤③:GROUP BY子句的結果能排序嗎

    • 答案是:“ 隨機的。”
    • GROUP BY子句結果的顯示是無序的。
  • 常見錯誤④:在WHERE子句中使用聚合函式

    • 只有SELECT子句和HAVING子句(以及ORDER BY子句)中能夠使用聚合函式。
    • -- 在WHERE子句中使用聚合函式會引發錯誤 
      SELECT product_type, COUNT(*)  
      FROM Product 
      WHERE COUNT(*) = 2 
      GROUP BY product_type;

為聚合結果指定條件

HAVING子句

  • SELECT <列名1>, <列名2>, <列名3>, …… 
    FROM <表名> 
    GROUP BY <列名1>, <列名2>, <列名3>, …… 
    HAVING <分組結果對應的條件>

  • 使用 HAVING 子句時 SELECT 語句的順序

    • SELECT → FROM → WHERE → GROUP BY → HAVING
  • HAVING子句要寫在GROUP BY子句之後

  • -- 從按照商品種類進行分組後的結果中,取出“包含的資料行數為2 行”的組
    SELECT product_type, COUNT() 
    FROM Product 
    GROUP BY product_type 
    HAVING COUNT() = 2;

HAVING子句的構成要素

  • HAVING 子句中 能夠使用的 3種要素如下

    • 常數
    • 聚合函式
    • GROUP BY子句中指定的列名(也就是聚合鍵)
    • -- HAVING子句的不正確使用方法 
      SELECT product_type, COUNT(*)  
      FROM Product 
      GROUP BY product_type 
      HAVING product_name = '圓珠筆';

相對於HAVING子句, 更適合寫在WHERE子句中的條件

  • WHERE 子句 = 指定行所對應的條件
  • HAVING 子句 = 指定組所對應的條件
  • 聚合鍵所對應的條件不應該書寫在HAVING子句當中,而應該書寫在WHERE子句當中。

對查詢結果進行排序

ORDER BY子句

SELECT <列名1>, <列名2>, <列名3>, …… 
FROM <表名> 
ORDER BY <排序基準列1>, <排序基準列2>, ……

-- 按照銷售單價由低到高(升序)進行排列 
SELECT product_id, product_name, sale_price, purchase_price
FROM Product ORDER BY sale_price;

  • ORDER BY 子句中書寫的列名稱為排序鍵

  • ORDER BY 子句都需要寫在 SELECT 語句的末尾。這是因為對資料行進行排序的操作必須在結果即將返回時執行

  • 子句的書寫順序

      1. SELECT 子句 → 2. FROM 子句 → 3. WHERE 子句 → 4. GROUP BY 子句 → 5. HAVING 子句 → 6. ORDER BY 子句

指定升序或降序

  • 降序排列時,在列名後面使用 DESC 關鍵字
  • 升序進行排列時,正式的書寫方式應該是使用關鍵字ASC
  • ASC 和 DESC 是 ascendent(上升的)和 descendent(下降的)這兩個單詞的縮寫。
  • 未指定ORDER BY子句中排列順序時會預設使用升序進行排列。
  • 由於 ASC 和 DESC 這兩個關鍵字是以列為單位指定的,因此可以 同時指定一個列為升序,指定其他列為降序。
-- 按照銷售單價由高到低(降序)進行排列 
SELECT product_id, product_name, sale_price, purchase_price
FROM Product ORDER BY sale_price DESC;

指定多個排序鍵

  • 規則是優先使用左側的鍵,如果該列存在相同值的話,再接著參考右側的鍵
-- 按照銷售單價和商品編號的升序進行排序 
SELECT product_id, product_name, sale_price, purchase_price
FROM Product ORDER BY sale_price, product_id;

NULL的順序

  • 排序鍵中包含NULL時,會在開頭或末尾進行彙總

在排序鍵中使用顯示用的別名

  • ORDER BY 子句中允許使用別名的

  • 使用 HAVING 子句時 SELECT 語句的順序

    • FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY

ORDER BY子句中可以使用的列

  • ORDER BY 子句中也可以使用存在於表中、但並不包含在 SELECT 子句之中的列
  • 可以使用聚合函式
-- SELECT子句中未包含的列也可以在ORDER BY子句中使用 
SELECT product_name, sale_price, purchase_price FROM Product ORDER BY product_id; -- product_id 不顯示在查詢結果中

不要使用列編號

  • 列編號是指SELECT 子句中的列按照從左到 右的順序進行排列時所對應的編號(1, 2, 3, …)
  • 第一,程式碼閱讀起來比較難
  • 第二,該排序功能將來會被刪除
-- 通過列名指定 
SELECT product_id, product_name, sale_price, purchase_price  
FROM Product ORDER BY sale_price DESC, product_id; -- 通過列編號指定 SELECT product_id, product_name, sale_price, purchase_price
FROM Product ORDER BY 3 DESC, 1;