12章 匯總數(shù)據(jù)
聚集函數(shù)(aggregate function) 運(yùn)行在行組上,計(jì)算和返回單個(gè)值的函數(shù)
1. 確定表中行數(shù)(或者滿足某個(gè)條件或包含某個(gè)特定值的行數(shù))。
2. 獲得表中行組的和。
3. 找出表列(或所有行或某些特定的行)的最大值、最小值和平均值。
SQL聚集函數(shù)
函 數(shù) 說(shuō) 明
AVG() 返回某列的平均值
COUNT() 返回某列的行數(shù)
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值之和
舉例:
AVG()函數(shù)
mysql> select avg(prod_price) as avg_price from products;
mysql> select avg(prod_price) as avg_price from products where vend_id = 1003; //指定條件
+-----------+
| avg_price |
+-----------+
| 13.212857 |
+-----------+
COUNT()函數(shù)
檢索客戶總數(shù):
mysql> select count(*) as num_cust from customers;
+----------+
| num_cust |
+----------+
| 5 |
+----------+
COUNT()函數(shù)有兩種使用方式:
1. 使用COUNT(*)對(duì)表中行的數(shù)目進(jìn)行計(jì)數(shù),不管表列中包含的是空值(NULL)還是非空值。
2. 使用COUNT(column)對(duì)特定列中具有值的行進(jìn)行計(jì)數(shù),忽略NULL值。
mysql> select count(cust_email) as num_cust from customers; //只對(duì)具有電子郵件地址的客戶計(jì)數(shù)
MAX()函數(shù)
返回指定列中的最大值, 需要指定列名, MAX()函數(shù)忽略列值為NULL的行。
mysql> select max(prod_price) as max_pricce from products;
MIN()函數(shù)
返回指定列的最小值。與MAX()一樣,MIN()要求指定列名,忽略列值為NULL的行
SUM()函數(shù)
mysql> select quantity from orderitems where order_num= 20005;
+----------+
| quantity |
+----------+
| 10 |
| 3 |
| 5 |
| 1 |
+----------+
mysql> select sum(quantity) as items_ordered from orderitems where order_num= 20005;
+---------------+
| items_ordered |
+---------------+
| 19 |
+---------------+
聚集不同值
使用DISTINCT
mysql> select avg(distinct prod_price) as avg_price from products where vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 15.998000 |
+-----------+
使用了DISTINCT后,此例子中的avg_price比較高,因?yàn)橛卸鄠€(gè)物品具有相同的較低價(jià)格。排除它們提升了平均價(jià)格。
組合聚集函數(shù)
mysql> select count(*) as num_items, min(prod_price) as price_min,max(prod_price) as price_max, avg(prod_price) as prive_avg from products;
+-----------+-----------+-----------+-----------+
| num_items | price_min | price_max | prive_avg |
+-----------+-----------+-----------+-----------+
| 14 | 2.50 | 55.00 | 16.133571 |
+-----------+-----------+-----------+-----------+
13章 分組數(shù)據(jù)
group by 分組允許把數(shù)據(jù)分為多個(gè)邏輯組,以便能對(duì)每個(gè)組進(jìn)行聚集計(jì)算.
創(chuàng)建分組
mysql> select vend_id, count(*) as num_prods from products;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| 1001 | 14 |
+---------+-----------+
mysql> select vend_id, count(*) as num_prods from products group by vend_id;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| 1001 | 3 |
| 1002 | 2 |
| 1003 | 7 |
| 1005 | 2 |
+---------+-----------+
在具體使用GROUP BY子句前,需要知道一些重要的規(guī)定:
1. GROUP BY子句可以包含任意數(shù)目的列。這使得能對(duì)分組進(jìn)行嵌套,為數(shù)據(jù)分組提供更細(xì)致的控制。
2. 如果在GROUP BY子句中嵌套了分組,數(shù)據(jù)將在最后規(guī)定的分組上進(jìn)行匯總。換句話說(shuō),在建立分組時(shí),指定的所有列都一起計(jì)算
(所以不能從個(gè)別的列取回?cái)?shù)據(jù))。
3. GROUP BY子句中列出的每個(gè)列都必須是檢索列或有效的表達(dá)式(但不能是聚集函數(shù))。如果在SELECT中使用表達(dá)式,則必須在
GROUP BY子句中指定相同的表達(dá)式。不能使用別名。
4. 除聚集計(jì)算語(yǔ)句外,SELECT語(yǔ)句中的每個(gè)列都必須在GROUP BY子句中給出。
5. 如果分組列中具有NULL值,則NULL將作為一個(gè)分組返回。如果列中有多行NULL值,它們將分為一組。
6. GROUP BY子句必須出現(xiàn)在WHERE子句之后,ORDER BY子句之前。
過(guò)濾分組
HAVING子句
1. HAVING非常類似于WHERE, 所有類型的WHERE子句都可以用HAVING來(lái)替代。唯一的差別是WHERE過(guò)濾行,而HAVING過(guò)濾分組。
2. HAVING支持所有WHERE操作符
mysql> select cust_id, count(*) as orders from orders group by cust_id having count(*)>=2;
+---------+--------+
| cust_id | orders |
+---------+--------+
| 10001 | 2 |
+---------+--------+
這里WHERE子句不起作用,因?yàn)檫^(guò)濾是基于分組聚集值而不是特定行值的
mysql> select vend_id,count(*) as num_prods from products where prod_price >=10 group by vend_id
--> having count(*) >=2;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| 1003 | 4 |
| 1005 | 2 |
+---------+-----------+
分組和排序
ORDER BY與GROUP BY
ORDER BY GROUP BY
+--------------------------+--------------------------------------------------
| 排序產(chǎn)生的輸出 | 分組行。但輸出可能不是分組的順序
+--------------------------+--------------------------------------------------
| 任意列都可以使用(甚至 | 只可能使用選擇列或表達(dá)式列,而且必須使用每個(gè)選擇
| 非選擇的列也可以使用) | 列表達(dá)式
+--------------------------+--------------------------------------------------
| 不一定需要 | 如果與聚集函數(shù)一起使用列(或表達(dá)式),則必須使用
+--------------------------+--------------------------------------------------
mysql> select order_num,sum(quantity*item_price) as ordertotal from orderitems group by order_num having sum(quantity*item_price)>=50;
+-----------+------------+
| order_num | ordertotal |
+-----------+------------+
| 20005 | 149.87 |
| 20006 | 55.00 |
| 20007 | 1000.00 |
| 20008 | 125.00 |
+-----------+------------+
mysql> select order_num, sum(quantity*item_price) as ordertotal from orderitems group by order_num having sum
-->(quantity*item_price)>=50 order by ordertotal;
+-----------+------------+
| order_num | ordertotal |
+-----------+------------+
| 20006 | 55.00 |
| 20008 | 125.00 |
| 20005 | 149.87 |
| 20007 | 1000.00 |
+-----------+------------+
SELECT子句順序
SELECT子句及其順序: 以下為必須遵循的順序。
子 句 說(shuō) 明 是否必須使用
SELECT 要返回的列或表達(dá)式 是
FROM 從中檢索數(shù)據(jù)的表 僅在從表選擇數(shù)據(jù)時(shí)使用
WHERE 行級(jí)過(guò)濾 否
GROUP BY 分組說(shuō)明 僅在按組計(jì)算聚集時(shí)使用
HAVING 組級(jí)過(guò)濾 否
ORDER BY 輸出排序順序 否
LIMIT 要檢索的行數(shù) 否
14章 使用子查詢
子查詢(subquery),即嵌套在其他查詢中的查詢。
mysql> select cust_id from orders where order_num in (select order_num from orderitems where prod_id='TNT2');
+---------+
| cust_id |
+---------+
| 10001 |
| 10004 |
+---------+
嵌套查詢順序:子查詢總是從內(nèi)向外處理
15章 聯(lián)結(jié)表
一些概念:
1. 聯(lián)結(jié)是一種機(jī)制,用來(lái)在一條SELECT語(yǔ)句中關(guān)聯(lián)表,因此稱之為聯(lián)結(jié)
2. 外鍵(foreign key): 外鍵為某個(gè)表中的一列,它包含另一個(gè)表的主鍵值,定義了兩個(gè)表之間的關(guān)系。
3. 如果數(shù)據(jù)存儲(chǔ)在多個(gè)表中,怎樣用單條SELECT語(yǔ)句檢索出數(shù)據(jù)?答案是使用聯(lián)結(jié)
4. SQL最強(qiáng)大的功能之一就是能在數(shù)據(jù)檢索查詢的執(zhí)行中聯(lián)結(jié)(join)表。
舉例:
mysql> select vend_name, prod_name,prod_price from vendors,products
--> where vendors.vend_id = products.vend_id order by vend_name,prod_name;
+-------------+----------------+------------+
| vend_name | prod_name | prod_price |
+-------------+----------------+------------+
| ACME | Bird seed | 10.00 |
| ACME | Carrots | 2.50 |
| ACME | Detonator | 13.00 |
| ACME | Safe | 50.00 |
| ACME | Sling | 4.49 |
| ACME | TNT (1 stick) | 2.50 |
| ACME | TNT (5 sticks) | 10.00 |
| Anvils R us | .5 ton anvil | 5.99 |
| Anvils R us | 1 ton anvil | 9.99 |
| Anvils R us | 2 ton anvil | 14.99 |
| Jet Set | JetPack 1000 | 35.00 |
| Jet Set | JetPack 2000 | 55.00 |
| LT Supplies | Fuses | 3.42 |
| LT Supplies | Oil can | 8.99 |
+-------------+----------------+------------+
這里,最大的差別是所指定的兩個(gè)列(prod_name 和prod_price)在一個(gè)表中,而另一個(gè)列(vend_name)在另一個(gè)表中。
通過(guò)where子句連接: where vendors.vend_id = products.vend_id
笛卡兒積(cartesian product) 由沒有聯(lián)結(jié)條件的表關(guān)系返回的結(jié)果為笛卡兒積, 笛卡爾積不是我們想要的結(jié)果
mysql> select vend_name, prod_name,prod_price from vendors,products order by vend_name,prod_name; //沒有where過(guò)濾
內(nèi)部聯(lián)結(jié) inner join
下面語(yǔ)句返回與上面相同的結(jié)果:
mysql> select vend_name,prod_name, prod_price from vendors inner join products on vendors.vend_id =
--> products.vend_id order by vend_name, prod_name;
+-------------+----------------+------------+
| vend_name | prod_name | prod_price |
+-------------+----------------+------------+
| ACME | Bird seed | 10.00 |
| ACME | Carrots | 2.50 |
| ACME | Detonator | 13.00 |
| ACME | Safe | 50.00 |
| ACME | Sling | 4.49 |
| ACME | TNT (1 stick) | 2.50 |
| ACME | TNT (5 sticks) | 10.00 |
| Anvils R us | .5 ton anvil | 5.99 |
| Anvils R us | 1 ton anvil | 9.99 |
| Anvils R us | 2 ton anvil | 14.99 |
| Jet Set | JetPack 1000 | 35.00 |
| Jet Set | JetPack 2000 | 55.00 |
| LT Supplies | Fuses | 3.42 |
| LT Supplies | Oil can | 8.99 |
+-------------+----------------+------------+
聯(lián)結(jié)多個(gè)表
mysql> select vend_name,prod_name, prod_price from vendors ,orderitems, products where products.vend_id =
--> vendors.vend_id and orderitems.prod_id = products.prod_id and order_num = 20005;
+-------------+----------------+------------+
| vend_name | prod_name | prod_price |
+-------------+----------------+------------+
| Anvils R us | .5 ton anvil | 5.99 |
| Anvils R us | 1 ton anvil | 9.99 |
| ACME | TNT (5 sticks) | 10.00 |
| ACME | Bird seed | 10.00 |
+-------------+----------------+------------+