Oracle_group by分組查詢_深入
在SQL Server中使用的分組查詢是ORDER BY子句,使用ORDER BY子句要同聚合函數配合使用才能完成分組查詢,在SELECT查詢的字段中如果字段沒有使用聚合函數就必須出現在ORDER BY子句中(即SELECT后邊的字段名要么出現在聚合函數中,要么在ORDER BY子句中使用)
在分組查詢中還可以配合使用HAVING子句,定義查詢條件。
使用group by進行分組查詢
在使用group by關鍵字時,在select列表中可以指定的項目是有限制的,select語句中僅許以下幾項:
〉被分組的列
〉為每個分組返回一個值得表達式,例如用一個列名作為參數的聚合函數
group by 有一個原則,就是 select 后面的所有列中,沒有使用聚合函數的列,必須出現在 group by 后面(重要)
group by實例
實例一
數據表:
姓名 科目 分數
張三 語文 80
張三 數學 98
張三 英語 65
李四 語文 70
李四 數學 80
李四 英語 90
期望查詢結果:
姓名 語文 數學 英語
張三 80 98 65
李四 70 80 90
代碼
create table testScore
(
tid int primary key identity(1,1),
tname varchar(30) null,
ttype varchar(10) null,
tscor int null
)
go
---插入數據insert into testScore values ('張三','語文',80)
insert into testScore values ('張三','數學',98)
insert into testScore values ('張三','英語',65)
insert into testScore values ('李四','語文',70)
insert into testScore values ('李四','數學',80)
insert into testScore values ('李四','英語',90)
select tname as '姓名' ,
max(case ttype when '語文' then tscor else 0 end) '語文',
max(case ttype when '數學' then tscor else 0 end) '數學',
max(case ttype when '英語' then tscor else 0 end) '英語'
from testScore
group by tname
實例二
有如下數據:(為了看得更清楚,我並沒有使用國家代碼,而是直接用國家名作為Primary Key)
| 國家(country) | 人口(population) |
| 中國 | 600 |
| 美國 | 100 |
| 加拿大 | 100 |
| 英國 | 200 |
| 法國 | 300 |
| 日本 | 250 |
| 德國 | 200 |
| 墨西哥 | 50 |
| 印度 | 250 |
根據這個國家人口數據,統計亞洲和北美洲的人口數量。應該得到下面這個結果。
| 洲 | 人口 |
| 亞洲 | 1100 |
| 北美洲 | 250 |
| 其他 | 700 |
代碼
SELECT SUM(population),
CASE country
WHEN '中國' THEN '亞洲'
WHEN '印度' THEN '亞洲'
WHEN '日本' THEN '亞洲'
WHEN '美國' THEN '北美洲'
WHEN '加拿大' THEN '北美洲'
WHEN '墨西哥' THEN '北美洲'
ELSE '其他' END
FROM Table_A
GROUP BY CASE country
WHEN '中國' THEN '亞洲'
WHEN '印度' THEN '亞洲'
WHEN '日本' THEN '亞洲'
WHEN '美國' THEN '北美洲'
WHEN '加拿大' THEN '北美洲'
WHEN '墨西哥' THEN '北美洲'
ELSE '其他' END;
同樣的,我們也可以用這個方法來判斷工資的等級,並統計每一等級的人數。SQL代碼如下;
SELECT
CASE WHEN salary <= 500 THEN '1'
WHEN salary > 500 AND salary <= 600 THEN '2'
WHEN salary > 600 AND salary <= 800 THEN '3'
WHEN salary > 800 AND salary <= 1000 THEN '4'
ELSE NULL END salary_class,
COUNT(*)
FROM Table_A
GROUP BY
CASE WHEN salary <= 500 THEN '1'
WHEN salary > 500 AND salary <= 600 THEN '2'
WHEN salary > 600 AND salary <= 800 THEN '3'
WHEN salary > 800 AND salary <= 1000 THEN '4'
ELSE NULL END;
對於groupby后面一般都是跟一個列名,但在該例子中通過case語句使分組變得跟強大了。
實例三
有如下數據
| 國家(country) | 性別(sex) | 人口(population) |
| 中國 | 1 | 340 |
| 中國 | 2 | 260 |
| 美國 | 1 | 45 |
| 美國 | 2 | 55 |
| 加拿大 | 1 | 51 |
| 加拿大 | 2 | 49 |
| 英國 | 1 | 40 |
| 英國 | 2 | 60 |
按照國家和性別進行分組,得出結果如下
| 國家 | 男 | 女 |
| 中國 | 340 | 260 |
| 美國 | 45 | 55 |
| 加拿大 | 51 | 49 |
| 英國 | 40 | 60 |
代碼
SELECT country,
SUM( CASE WHEN sex = '1' THEN
population ELSE 0 END), --男性人口SUM( CASE WHEN sex = '2' THEN
population ELSE 0 END) --女性人口FROM Table_A
GROUP BY country;
GROUP BY子句中的NULL值處理
當GROUP BY子句中用於分組的列中出現NULL值時,將如何分組呢?SQL中,NULL不等於NULL(在WHERE子句中有過介紹)。然而,在GROUP BY子句中,卻將所有的NULL值分在同一組,即認為它們是“相等”的。
HAVING子句
GROUP BY子句分組,只是簡單地依據所選列的數據進行分組,將該列具有相同值的行划為一組。而實際應用中,往往還需要刪除那些不能滿足條件的行組,為了實現這個功能,SQL提供了HAVING子句。語法如下。
SELECT column, SUM(column)
FROM table
GROUP BY column
HAVING SUM(column) condition value
說明:HAVING通常與GROUP BY子句同時使用。當然,語法中的SUM()函數也可以是其他任何聚合函數。DBMS將HAVING子句中的搜索條件應用於GROUP BY子句產生的行組,如果行組不滿足搜索條件,就將其從結果表中刪除。
HAVING子句的應用
從TEACHER表中查詢至少有兩位教師的系及教師人數。
實現代碼:

SELECT DNAME, COUNT(*) AS num_teacher

FROM TEACHER

GROUP BY DNAME

HAVING COUNT(*)>=2
HAVING子句與WHERE子句的區別
HAVING子句和WHERE子句的相似之處在於,它也定義搜索條件。但與WHERE子句不同,HAVING子句與組有關,而不是與單個的行有關。
1、如果指定了GROUP BY子句,那么HAVING子句定義的搜索條件將作用於這個GROUP BY子句創建的那些組。
2、如果指定WHERE子句,而沒有指定GROUP BY子句,那么HAVING子句定義的搜索條件將作用於WHERE子句的輸出,並把這個輸出看作是一個組。
3、如果既沒有指定GROUP BY子句也沒有指定WHERE子句,那么HAVING子句定義的搜索條件將作用於FROM子句的輸出,並把這個輸出看作是一個組。
4、在SELECT語句中,WHERE和HAVING子句的執行順序不同。在本書的5.1.2節介紹的SELECT語句的執行步驟可知,WHERE子句只能接收來自FROM子句的輸入,而HAVING子句則可以接收來自GROUP BY子句、WHERE子句和FROM子句的輸入。



