一、條件查詢語句
WHERE 和 HAVING 的區(qū)別:
- WHERE是直接對表中的字段進行限定,來篩選結(jié)果;
- HAVING則需要跟分組關(guān)鍵字GROUP BY一起使用,通過對分組字段或分組計算函數(shù)進行限定,來篩選結(jié)果。
雖然它們都是對查詢進行限定,卻有著各自的特點和適用場景。
WHERE
WHERE關(guān)鍵字的特點是,直接用表的字段對數(shù)據(jù)集進行篩選。如果需要通過關(guān)聯(lián)查詢從其他的表獲取需要的信息,那么執(zhí)行的時候,也是先通過WHERE條件進行篩選,用篩選后的比較小的數(shù)據(jù)集進行連接。這樣一來, 連接過程中占用的資源比較少,執(zhí)行效率也比較高。
HAVING
HAVING不能單獨使用,必須要跟GROUP BY 一起使用。
我們可以把GROUP BY理解成對數(shù)據(jù)進行分組,方便我們對組內(nèi)的數(shù)據(jù)進行統(tǒng)計計算。
它們兩個典型的區(qū)別就是:
- 如果需要通過連接從關(guān)聯(lián)表中獲取需要的數(shù)據(jù),WHERE 是先篩選后連接,而HAVING是先連接后篩選。
- WHERE可以直接使用表中的字段作為篩選條件,但不能使用分組中的計算函數(shù)作為篩選條件;HAVING必須要與GROUP BY配合使用,可以把分組計算的函數(shù)和分組字段作為篩選條件。
這決定了,在需要對數(shù)據(jù)進行分組統(tǒng)計的時候,HAVING 可以完成WHERE不能完成的任務。這是因為,在查詢語法結(jié)構(gòu)中,WHERE在GROUP BY之前,所以無法對分組結(jié)果進行篩選。HAVING在GROUP BY之后,可以使用分組字段和分組中的計算函數(shù),對分組的結(jié)果集進行篩選,這個功能是WHERE無法完成的。
這么說可能不太好理解,舉個小例子理解一下。假如超市經(jīng)營者提出,要查詢一下是哪個收銀員、在哪天賣了2單商品。
這種必須先分組才能篩選的查詢,用WHERE語句實現(xiàn)就比較難,我們可能要分好幾步,通過把中間結(jié)果存儲起來,才能搞定。但是用HAVING,則很輕松,代碼如下:
SELECT
a. transdate, c.operatorname
FROM
demo. transactionhead AS a
JOIN
demo. transactiondetails AS b ON (a. transactionid = b. transactionid)
JOIN
demo.operator AS C ON (a.operatorid = c. operatorid)
GROUP BY a. transdate, c. operatorname
HAVING count(*)=2; --銷售了2單
不過需要注意的是,WHERE和HAVING也不是互相排斥的,也可以在一 個查詢里面同使用WHERE和HAVING。
二、聚合函數(shù)
MySQL中有5種聚合函數(shù)較為常用,分別是:
- 求和函數(shù)SUM)
可以返回指定字段值的和。 - 求平均函數(shù)AVG()
- 最大值函數(shù)MAX()
- 最小值函數(shù)MIN()
- 計數(shù)函數(shù)COUNT()
先創(chuàng)建三個表,基于這三個表的基礎(chǔ)上對聚合函數(shù)進行操作理解:
-- 創(chuàng)建銷售明細表
CREATE TABLE demo.transactiondetails
(
transactionid INT NOT NULL,
itemnumber INT NOT NULL,
quantity INT,
price DECIMAL(10,2),
salesvalue DECIMAL(10,2),
-- 聯(lián)合主鍵
PRIMARY KEY(transactionid,itemnumber)
);
銷售明細表(transactiondetails):
銷售單頭表(transactionhead):
商品信息表(goodmaster):
1、SUM()
SUM () 函數(shù)可以返回指定字段值的和。我們可以用它來獲得用戶某個門店,每天、每種商品的銷售總計數(shù)據(jù):
SELECT
LEFT(b.transdate, 10), -- 從關(guān)聯(lián)表獲取交易時間,并且通過LEFT函數(shù),獲取交易的年月日
c.goodsname, -- 從關(guān)聯(lián)表獲取商品名稱
SUM(a.quantity), -- 數(shù)量求和
SUM(a.salesvalue) -- 金額求和
FROM
demo.transactiondetails a
JOIN
demo.transactionhead b ON (a.transactionid = b. transactionid)
JOIN
demo.goodmaster c ON (a.itemnumber = c.itemnumber)
GROUP BY LEFT(b.transdate,10), c.goodsname -- 分組
ORDER BY LEFT(b.transdate,10), c.goodsname; -- 排序
查詢結(jié)果:
這里引入了兩個關(guān)鍵字:
- LEFT(str, n):表示返回字符串str最左邊的n個字符。
- ORDER BY:表示按照指定的字段排序。
需要注意的是,求和函數(shù)獲取的是分組中的合計數(shù)據(jù),所以要對分組的結(jié)果有準確的把握,否則就很容易搞錯。這也就是說,我們要知道是按什么字段進行分組的。
- 如果是按多個字段分組,就要知道字段之間有什么樣的層次關(guān)系;
- 如果是按照以字段作為變量的某個函數(shù)進行分組的,就要知道這個函數(shù)的返回值是什么,返回值又是如何影響分組的等。
2、AVG()、MAX()、MIN()
AVG()
首先,我們來學習下計算平均值的函數(shù)AVG ()。它的作用是,通過計算分組內(nèi)指定字段值的和,以及分組內(nèi)的記錄數(shù),算出分組內(nèi)指定字段的平均值。
舉個例子,如果用戶需要計算每天、每種商品,平均一次賣出多少個、多少錢,這個時候,我們就可以用到AVG () 函數(shù)了如下所示:
SELECT
LEFT(a. transdate,10),
c.goodsname,
AVG (b.quantity), -- 平均數(shù)量
AVG (b.salesvalue) -- 平均金額
FROM
demo. transactionhead a
JOIN
demo. transactiondetails b ON (a.transactionid = b.transactionid)
JOIN
demo. goodmaster c ON (b.itemnumber = c.itemnumber )
GROUP BY LEFT(a. transdate,10) ,c.goodsname
ORDER BY LEFT(a. transdate,10) ,c.goodsname;
查詢結(jié)果:
MAX()、MIN()
MAX()表示獲取指定字段在分組中的最大值,MIN()表示獲取指定字段在分組中的最小值。它們的實現(xiàn)原理差不多。
我們還是來看具體的例子。假如戶要求計算每天里的一次銷售的最大數(shù)量和最大金額,就可以用下面的代碼,得到我們需要的結(jié)果
SELECT
LEFT(a. transdate,10),
MAX(b.quantity),
MAX(b.salesvalue)
FROM
demo. transactionhead a
JOIN
demo. transactiondetails b ON (a.transactionid = b.transactionid)
JOIN
demo. goodmaster c ON (b.itemnumber = c.itemnumber )
GROUP BY LEFT(a. transdate,10) ,c.goodsname
ORDER BY LEFT(a. transdate,10) ,c.goodsname;
注意,MAX (字段)這個函數(shù)返回分組集中最大的那個值。如果你要查詢MAX (字段1)和MAX (字段2),而它們是相互獨立、分別計算的,千萬不要想當然地認為結(jié)果在同一條記錄上。
3、COUNT()
通過COUNT (),我們可以了解數(shù)據(jù)集的大小,這對系統(tǒng)優(yōu)化十分重要。
比如分頁策略,這個策略能夠?qū)崿F(xiàn)的一個關(guān)鍵,就是要計算出符合條件的記錄一共有多少條,之后才能計算出一共有幾頁、能不能翻頁或跳轉(zhuǎn)。
要計算記錄數(shù),就要用到COUNT()函數(shù)了。這個函數(shù)有兩種情況。
- COUNT (*) :統(tǒng)計一共有多少條記錄;
- COUNT (字段) :統(tǒng)計有多少個不為空的字段值。
COUNT (*)
如果COUNT (*)與GROUP BY 一起使用,就表示統(tǒng)計分組內(nèi)有多少條數(shù)據(jù)。它也可以單獨使用,這就相當于數(shù)據(jù)集全體是一個分組,統(tǒng)計全部數(shù)據(jù)集的記錄數(shù)。
那么,如果超市經(jīng)營者想知道,每天、每種商品都有幾次銷售,我們就需要按天、按商品名稱,進行分組查詢:
SELECT
LEFT(a.transdate, 10), c.goodsname, COUNT(*) -- 統(tǒng)計銷售次數(shù)
FROM
demo. transactionhead a
JOIN
demo. transactiondetails b ON (a.transactionid = b.transactionid)
JOIN
demo. goodmaster c ON (b.itemnumber = c.itemnumber )
GROUP BY LEFT(a. transdate,10) ,c.goodsname
ORDER BY LEFT(a. transdate,10) ,c.goodsname;
運行結(jié)果:文章來源:http://www.zghlxwxcb.cn/news/detail-853077.html
COUNT (字段)
COUNT (字段)用來統(tǒng)計分組內(nèi)這個字段的值出現(xiàn)了多少次。如果字段值是空,就不統(tǒng)計。
針對這個表:文章來源地址http://www.zghlxwxcb.cn/news/detail-853077.html
- 如果我們要統(tǒng)計字段"cashierNo" 出現(xiàn)了多少次,就要用到函數(shù)COUNT (cashierNo), 結(jié)果是3次;
- 如果我們要統(tǒng)計字段"memberId" 出現(xiàn)了多少次,就要用到函數(shù)COUNT (memberId), 結(jié)果是1次。
到了這里,關(guān)于MySQL學習筆記3——條件查詢和聚合函數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!