一、SQL having子句簡介
在 SQL 中增加 HAVING 子句原因是,WHERE 關鍵字無法與聚合函數一起使用。
HAVING 子句可以讓我們篩選分組后的各組數據。
1、SQL HAVING 語法:operator 代表運算操作符、aggregate_function 代表聚合函數
SELECT column_name, aggregate_function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name HAVING aggregate_function(column_name) operator value;
2、示例:
下面是選自 "Websites" 表的數據: +----+--------------+---------------------------+-------+---------+
| id | name | url | alexa | country |
+----+--------------+---------------------------+-------+---------+
| 1 | Google | https://www.google.cm/ | 1 | USA |
| 2 | 淘寶 | https://www.taobao.com/ | 13 | CN |
| 3 | 菜鳥教程 | http://www.runoob.com/ | 4689 | CN |
| 4 | 微博 | http://weibo.com/ | 20 | CN |
| 5 | Facebook | https://www.facebook.com/ | 3 | USA |
| 7 | stackoverflow | http://stackoverflow.com/ | 0 | IND |
+----+---------------+---------------------------+-------+---------+
下面是 "access_log" 網站訪問記錄表的數據: mysql> SELECT * FROM access_log; +-----+---------+-------+------------+
| aid | site_id | count | date |
+-----+---------+-------+------------+
| 1 | 1 | 45 | 2016-05-10 |
| 2 | 3 | 100 | 2016-05-13 |
| 3 | 1 | 230 | 2016-05-14 |
| 4 | 2 | 10 | 2016-05-14 |
| 5 | 5 | 205 | 2016-05-14 |
| 6 | 4 | 13 | 2016-05-15 |
| 7 | 3 | 220 | 2016-05-15 |
| 8 | 5 | 545 | 2016-05-16 |
| 9 | 3 | 201 | 2016-05-17 |
+-----+---------+-------+------------+
9 rows in set (0.00 sec)
(1)現在我們想要查找總訪問量大於 200 的網站。我們使用下面的 SQL 語句:
SELECT Websites.name, Websites.url, SUM(access_log.count) AS nums FROM (access_log INNER JOIN Websites ON access_log.site_id=Websites.id) GROUP BY Websites.name HAVING SUM(access_log.count) > 200;
(2)現在我們想要查找總訪問量大於 200 的網站,並且 alexa 排名小於 200。我們在 SQL 語句中增加一個普通的 WHERE 子句:
SELECT Websites.name, SUM(access_log.count) AS nums FROM Websites INNER JOIN access_log ON Websites.id=access_log.site_id WHERE Websites.alexa < 200 GROUP BY Websites.name HAVING SUM(access_log.count) > 200;
二、Having子句和Where子句
1、區別:
(1)where 不能放在GROUP BY 后面
(2)HAVING 是跟GROUP BY 連在一起用的,放在GROUP BY 后面,此時的作用相當於WHERE
(3)WHERE 后面的條件中不能有聚集函數,比如SUM(),AVG()等,而HAVING 可以
where 和 having 都是對查詢結果的一種篩選,說的書面點就是設定條件的語句。
2、聚合函數:聚合函數有時候也叫統計函數,它們的作用通常是對一組數據的統計,比如說求最大值,最小值,總數,平均值( MAX,MIN,COUNT, AVG)等。
這些函數和其它函數的根本區別就是它們一般作用在多條記錄上。簡單舉個例子:SELECT SUM(sal) FROM emp,這里的SUM作用是統計emp表中 sal(工資)字段的總和,結果就是該查詢只返回一個結果,即工資總和。
通過使用GROUP BY 子句,可以讓 SUM 和 COUNT 這些函數對屬於一組的數據起作用。
3、where子句:where 子句僅僅用於從 from 子句中返回的值,from 子句返回的每一行數據都會用 where 子句中的條件進行判斷篩選。
where子句中允許使用比較運算符(>,<,>=,<=,<>,!=|等)和邏輯運算符(and,or,not)。
4、having子句:having子句通常是與 order by 子句一起使用的。因為 having 的作用是對使用 group by 進行分組統計后的結果進行進一步的篩選。
-- 舉個例子:現在需要找到部門工資總和大於10000的部門編號?
-- 第一步:先按部門分組
select deptno,sum(sal) from emp group by deptno; -- 篩選結果如下:
DEPTNO SUM(SAL) ------ ----------
30 9400
20 10875
10 8750
-- 可以看出我們想要的結果了。不過現在我們如果想要部門工資總和大於10000的呢? -- 那么想到了對分組統計結果進行篩選的having來幫我們完成。
-- 第二步:利用 having子句篩選
select deptno,sum(sal) from emp group by deptno having sum(sal)>10000; -- 篩選結果如下:
DEPTNO SUM(SAL) ------ ----------
20 10875
-- 當然這個結果正是我們想要的。
5、下面我們通過 where 子句和 having 子句的對比,更進一步的理解它們。
在查詢過程中聚合語句 (sum,min,max,avg,count) 要比 having 子句優先執行,簡單的理解為只有有了統計結果后我才能執行篩選。
where子句在查詢過程中執行優先級別優先於聚合語句(sum,min,max,avg,count),因為它是一句一句篩選的。
HAVING子句可以讓我們篩選成組后的對各組數據篩選,而WHERE子句在聚合前先篩選記錄。
-- 如現在我們想要部門號不等於10的部門並且工資總和大於8000的部門編號? -- 我們這樣分析: -- 1、通過where子句篩選出部門編號不為10的部門, -- 2、然后在對部門工資進行統計, -- 3、然后再使用having子句對統計結果進行篩選。
select deptno,sum(sal) from emp where deptno!='10' group by deptno having sum(sal)>8000; -- 篩選結果如下:
DEPTNO SUM(SAL) ------ ----------
30 9400
20 10875
簡單總結執行優先級就是:where 子句 > 聚合語句 > having 子句
簡單的說就是:先篩選之后再條件分組,就用 where;先分組之后再條件篩選,就用 having。
6、異同點
它們的相似之處就是定義搜索條件,不同之處是 where 子句為單個篩選,而 having 子句與組有關,而不是與單個的行有關。
理解 having 子句和 where 子句最好的方法就是基礎 select 語句中的那些句子的處理次序:where 子句只能接收 from 子句輸出的數據,而 having 子句則可以接受來自 group by,where 或者 from 子句的輸入。