一、匯總數據
工作中經常需要匯總數據而不是將它們全部檢索出來(實際數據本身:返回實際數據是對時間和處理資源的浪費),這種類型的檢索有以下特點:
①確定表中的行數(或者滿足某個條件或包含某個特定值的行數)
②獲得表中行組的和
③找出表列(或所有行或某些特定的行)的最大值、最小值和平均值
聚集函數(aggregate function):運行在行組上,計算和返回單個值的函數(MySQL還支持一些列的標准偏差聚集函數);
SQL聚集函數如下表:
1、avg()函數
avg()通過對表中行數計數並計算特定列值之和,求得該列的平均值;avg()可用來返回所有列平均值,也可用來返回特定列的平均值;
select avg(prod_price) as avg_price from pfoducts;
此select語句返回值avg_price,它包含producs表中所有產品的平均價格,avg_price是一個別名;
avg()也可以用來確定特定列或行的平均值,例子如下:
select avg_(prod_price) as avg_price from products where vend_id = 1003;
這條SQL語句包含了where子語句,僅過濾出vend_id為1003的產品,avg_price中返回該供應商的產品的平均值;
PS:avg()只能用來確定特定數值列的平均值,而且列名必須作為函數參數給出,為了獲得多個列的平均值,必須使用多個avg()函數{avg()函數忽略列值為NULL的行};
2、count()函數
count()函數進行計數,可利用count()確定表中行的數目或符合特定條件的行的數目;
count()函數有兩種使用方式:
①使用count(*)對表中行的數目進行計數,不管表列中包含的是空值(null)還是非空值;
②使用count(column)對特定列中具有值的行進行計數,忽略null值;
select count(*) as num_cust from customers;
這條SQL語句利用count(*)對customers表中所有行計數,計數值在num_cust中返回;
select count(cust_email) as cum_cust from customers;
這條SQL語句使用count(cust_email)對cust_email列中有值的行進行計數;
PS:如果指定列名,則指定列的值為空的行被count()函數忽略,但如果count()函數中用的是星號(*),則不忽略;
3、max()函數
max()返回指定列中的最大值,max()要求指定列名,例子如下:
select max(prod_price) as max_price from products;
這條SQL語句中國返回products表中price列的最大值;
PS:MySQL允許max()用來返回任意列中的最大值,包括返回文本列的最大值;但用於文本數據時,如果數據按相應的列排序,則max()返回最后一行(max()函數忽略列值為null的行)
4、min()函數
min()返回指定列的最小值,min()也要求指定列名,例子如下:
select min(prod_price) as min_price from products;
這條SQL語句中min()返回products表中price列最小值;
PS:MySQL允許min()用來返回任意列中的最小值,包括返回文本列的最小值;但用於文本數據時,如果數據按相應的列排序,則min()返回最前面的行(min()函數忽略列值為null的行)
5、sum()函數
sum()函數用來返回指定列值的和(總計);例子如下:
select sum(quantity) as items_ordered from orderitems where order_num = 20005;
函數sum()返回orderitems中所有quantity列的值之和,where子句保證只統計某個指定列的數值;
PS:利用標准的算數操作符,所有聚集函數都可用來執行多個列上的計算(sum()函數忽略列值為null的行)
6、distinct與聚集函數
MySQL5.0.3以及之后的版本,聚集函數和distinct可以搭配使用,比如:
①對所有的行執行計算,指定all參數或不給參數(all是默認所有行為,不需要指定,如果不指定distinct,則假定為all);
②只包含不同的值,指定distinct參數;
③如果指定列名,則distinct只能用於count();distinct不能用於count(*),因此不允許使用count(distinct);distinct必須使用列名,不能用於計算或者表達式;
select avg(distinct prod_price) as avg_price from products where vend_id = 1003;
這條SQL語句中,使用avg()函數返回vend列中vend_id=1003的對應的price平均價格,因為使用了distinct參數,因此平均值只考慮不同的值(唯一值)
7、組合聚集函數
select語句可以包含多個聚集函數,比如:
select count(*) as num_items,
min(prod_price) as price_min,
max(prod_price) as price_max,
avg(prod_price) as price_avg
from products;
這條SQL語句,使用了單條select語句執行4個聚集計算,返回四個值(products表中items的數目、price的最高、最低以及平均值)
PS:在指定別名以包含某個聚集函數的結果時,不應該使用表中實際的列名;這樣便於使用SQL更加容易和理解,以及排除方便排除錯誤。
二、分組數據
1、group by創建分組
在MySQL中,分組是在select語句中的group by子句中建立的,比如:
select vend-id,count(*) as num_prods from products group by vend_id;
這條SQL語句指定了2個列,group by指示MySQL按照vend_id排序並且分組(如果使用group by,則不必指定要計算的每個組)
group by子句指示指示MySQL分組數據,然后都每個組而不是整個結果集進行聚集;關於group by使用,請注意以下規則:
①group by子句可以包含任意數目的列(使得對分組進行嵌套,為數據分組提供更細致的控制);
②如果在group by子句中嵌套分組,數據將在最后規定的分組上進行匯總,即:建立分組時,指定的所有列都一起計算(所以不能從個別列取回數據);
③group by子句中列出的每個列都必須是檢索列或有效的表達式(但不能是聚集函數),如果在select中使用表達式,則必須在group by子句中指定相同的表達式(不能使用別名);
④除了聚集計算語句外,select中每個列都必須在group by子句中給出;
⑤如果分組列中具有null值,則null將作為一個分組返回(如果列中有多行null值,他們將分為一組);
⑥group by子句必須出現在where子句之后,order by子句之前;
PS:使用with rollup關鍵字,可以得到每個分組以及每個分組匯總級別(針對每個分組)的值。
2、having過濾分組
where子句都可以用having代替,區別在於where過濾行,having過濾分組;having支持所有的where操作符,比如:
select cust_id,count(*) as orders from orders group by cust_id having count(*) >= 2;
這條SQL語句中的having子句過濾count(*)>=2(2個以上的分組)的那些分組;
having和where的區別:
where在數據分組前進行過濾,having在數據分組后進行過濾;where排除的行不包括在分組中(這可能會改變計算值,從而影響having子句中基於這些值過濾掉的分組)
having和where可以同時使用,比如:
select vend_id, count(*) as num_prods from products where prod_price>=10 group by vend_id having count(*)>= 2;
這條SQL語句中,where子句過濾掉所有prod_price至少為10的行,然后按照vend_id分組數據;having子句過濾技術為2或2以上的分組;
3、分組和排序
group by和order by的區別:
order by的重要性:一般使用group by子句時,應該也給出order by子句,這是保證數據正確性的唯一方法(千萬不要依賴group by排序數據)。
4、select子句順序