1. 程式人生 > 其它 >淺析SQL having子句、如何使用having子句及where子句與having子句的區別

淺析SQL having子句、如何使用having子句及where子句與having子句的區別

一、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 子句的輸入。