目標(biāo):
10.1 數(shù)據(jù)分組
10.2 創(chuàng)建分組
10.3 過濾分組
10.4 分組和排序
10.5 SELECT 子句順序
這一課介紹如何分組數(shù)據(jù)炸宵,以便匯總表內(nèi)容的子集筐乳。這涉及兩個(gè)新
SELECT 語句子句:GROUP BY 子句和 HAVING 子句衅澈。
10.1 數(shù)據(jù)分組
使用分組可以將數(shù)據(jù)分為多個(gè)邏輯組,對(duì)每個(gè)組進(jìn)行聚集計(jì)算展蒂。
10.2 創(chuàng)建分組
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id;#分組根據(jù)
輸出:# vend_id num_prods?FNG01 2? DLL01 4? BRS01 3
在使用 GROUP BY 子句前呢簸,需要知道一些重要的規(guī)定。?
1. GROUP BY 子句可以包含任意數(shù)目的列漓概,因而可以對(duì)分組進(jìn)行嵌套漾月,更細(xì)致地進(jìn)行數(shù)據(jù)分組。?
2.如果在 GROUP BY 子句中嵌套了分組胃珍,數(shù)據(jù)將在最后指定的分組上進(jìn)行匯總栅屏。換句話說,在建立分組時(shí)堂鲜,指定的所有列都一起計(jì)算(所以不能從個(gè)別的列取回?cái)?shù)據(jù))栈雳。?
3. GROUP BY 子句中列出的每一列都必須是檢索列或有效的表達(dá)式(但不能是聚集函數(shù))。如果在 SELECT 中使用表達(dá)式缔莲,則必須在 GROUP BY 子句中指定相同的表達(dá)式哥纫。不能使用別名。
4.大多數(shù)SQL 實(shí)現(xiàn)不允許 GROUP BY 列帶有長度可變的數(shù)據(jù)類型(如文本或備注型字段)痴奏。
5.除聚集計(jì)算語句外蛀骇,SELECT 語句中的每一列都必須在 GROUP BY 子句中給出。?
6.如果分組列中包含具有 NULL 值的行读拆,則 NULL 將作為一個(gè)分組返回擅憔。 如果列中有多行 NULL 值,它們將分為一組檐晕。?
7.GROUP BY 子句必須出現(xiàn)在 WHERE 子句之后暑诸,ORDER BY 子句之前蚌讼。
提示:ALL 子句?
Microsoft SQL Server 等有些 SQL 實(shí)現(xiàn)在 GROUP BY 中支持可選的 ALL 子句。這個(gè)子句可用來返回所有分組个榕,即使是沒有匹配行的分組也返 回(在此情況下篡石,聚集將返回 NULL)。具體的 DBMS 是否支持 ALL西采, 請(qǐng)參閱相應(yīng)的文檔凰萨。
注意:通過相對(duì)位置指定列
有的 SQL 實(shí)現(xiàn)允許。例如械馆,GROUP BY 2, 1 可表示按選擇的第二個(gè)列分組胖眷,然后再按第一個(gè)列分組。雖然這種速記語法很方便霹崎,但并非所有 SQL 實(shí)現(xiàn)都支持珊搀,并且使用它容易在編輯 SQL 語句時(shí)出錯(cuò)。
10.3 過濾分組( HAVING? 關(guān)鍵詞)
提示:HAVING 支持所有 WHERE 操作符
在第 4 課和第 5 課中仿畸,我們學(xué)習(xí)了 WHERE 子句的條件(包括通配符條件和帶多個(gè)操作符的子句)。學(xué)過的這些有關(guān) WHERE 的所有技術(shù)和選項(xiàng)都適用于 HAVING朗和。它們的句法是相同的错沽,只是關(guān)鍵字有差別。
說明:HAVING 和 WHERE 的差別 這里有另一種理解方法眶拉,WHERE 在數(shù)據(jù)分組前進(jìn)行過濾千埃,HAVING 在數(shù)據(jù)分組后進(jìn)行過濾。這是一個(gè)重要的區(qū)別忆植,WHERE 排除的行不包括在 分組中放可。這可能會(huì)改變計(jì)算值,從而影響 HAVING 子句中基于這些值過濾掉的分組朝刊。
SELECT cust_id, COUNT(*) AS orders
FROM Orders
GROUP BY cust_id
HAVING COUNT(*) >= 2;
輸出:# cust_id, orders?'1000000001', '2'
SELECT vend_id, COUNT(*) AS num_prods?
FROM Products?
WHERE prod_price >= 4?
GROUP BY vend_id?
HAVING COUNT(*) >= 2;
輸出:'FNG01', '2' 'BRS01', '3'
說明:使用 HAVING 和 WHERE?
HAVING 與 WHERE 非常類似耀里,如果不指定 GROUP BY,則大多數(shù) DBMS 會(huì)同等對(duì)待它們拾氓。不過冯挎,你自己要能區(qū)分這一點(diǎn)。使用 HAVING 時(shí)應(yīng) 該結(jié)合 GROUP BY 子句咙鞍,而 WHERE 子句用于標(biāo)準(zhǔn)的行級(jí)過濾房官。
10.4 分組和排序
提示:不要忘記 ORDER BY
一般在使用 GROUP BY 子句時(shí),應(yīng)該也給出 ORDER BY 子句续滋。這是保證數(shù)據(jù)正確排序的唯一方法翰守。千萬不要僅依賴 GROUP BY 排序數(shù)據(jù)。
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3;
輸出:
SELECT order_num, COUNT(*) AS items?
FROM OrderItems?
GROUP BY order_num?
HAVING COUNT(*) >= 3?
ORDER BY items,order_num;
輸出:
10.5 SELECT 子句順序
10.6 小結(jié)
上一課介紹了如何用 SQL 聚集函數(shù)對(duì)數(shù)據(jù)進(jìn)行匯總計(jì)算疲酌。這一課講授了如何使用 GROUP BY 子句對(duì)多組數(shù)據(jù)進(jìn)行匯總計(jì)算蜡峰,返回每個(gè)組的結(jié)果。我們看到了如何使用 HAVING 子句過濾特定的組,還知道了 ORDER BY和 GROUP BY 之間以及 WHERE 和 HAVING 之間的差異事示。
-- ----------第10課 分組數(shù)據(jù)----------------------
-- 10.1 數(shù)據(jù)分組
-- 10.2 創(chuàng)建分組
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id;
-- 10.3 過濾分組
SELECT cust_id, COUNT(*) AS orders
FROM Orders
GROUP BY cust_id
HAVING COUNT(*) >= 2;
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
WHERE prod_price >= 4
GROUP BY vend_id
HAVING COUNT(*) >= 2;
-- 10.4 分組和排序
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3;
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3
ORDER BY items,order_num;
-- 10.5 SELECT 子句順序
10.7 挑戰(zhàn)題
1. OrderItems 表包含每個(gè)訂單的每個(gè)產(chǎn)品早像。編寫 SQL 語句,返回每個(gè)訂單號(hào)(order_num)各有多少行數(shù)(order_lines)肖爵,并按 order_lines對(duì)結(jié)果進(jìn)行排序卢鹦。
SELECT order_num,count(*) AS order_lines
FROM orderitems
GROUP BY order_num
ORDER BY order_lines;
2. 編寫 SQL 語句,返回名為 cheapest_item 的字段劝堪,該字段包含每個(gè)供應(yīng)商成本最低的產(chǎn)品(使用 Products 表中的 prod_price)冀自,然后從最低成本到最高成本對(duì)結(jié)果進(jìn)行排序。
SELECT vend_id,MIN(prod_price) AS cheapest_item
FROM products
GROUP BY vend_id
ORDER BY cheapest_item;
3. 確定最佳顧客非常重要秒啦,請(qǐng)編寫 SQL 語句熬粗,返回至少含 100 項(xiàng)的所有訂單的訂單號(hào)(OrderItems 表中的 order_num)。
SELECT order_num
FROM OrderItems
GROUP BY order_num
HAVING SUM(quantity) >= 100
ORDER BY order_num;
4. 確定最佳顧客的另一種方式是看他們花了多少錢余境。編寫 SQL 語句驻呐,返回總價(jià)至少為 1000 的所有訂單的訂單號(hào)(OrderItems 表中的order_num)。提示:需要計(jì)算總和(item_price 乘以quantity)芳来。按訂單號(hào)對(duì)結(jié)果進(jìn)行排序含末。
SELECT order_num, SUM(item_price*quantity) AS total_price
FROM OrderItems
GROUP BY order_num
HAVING SUM(item_price*quantity) >= 1000
ORDER BY order_num;
5. 下面的 SQL 語句有問題嗎?(嘗試在不運(yùn)行的情況下指出即舌。)SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY items
HAVING COUNT(*) >= 3
ORDER BY items, order_num;
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3
ORDER BY items, order_num;