方式一:select * from 學生表 where 姓名 in(select 姓名 from 學生表 group by 姓名 having count(姓名)>=2)
分析:from 學生表 :找到要查詢的表名, where 姓名 in:過濾條件讓姓名符合小括號里面內容 group by 姓名 :按照姓名來分組,也就是說姓名相同的會放在同一組里面,其他字段可能包括多條信息,having count(姓名)>=2:過濾分組內容中姓名達到兩個以及以上的信息)
方式二:select 姓名,count(姓名) from 學生表 group by 姓名 having count(姓名)>=2
注意方式二:select 姓名 from 學生表 group by 姓名 having count(姓名)>=2即可,count(姓名)是自己又在返回的視圖看到了另一個字段,這個字段用來顯示出現的重復姓名的次數。
GROUP BY語句,經過研究和練習,終於明白如何使用了,在此記錄一下同時添加了一個自己舉的小例子,通過寫這篇文章來加深下自己學習的效果,還能和大家分享下,同時也方便以后查閱,一舉多得
一、GROUP BY
GROUP BY語句用來與聚合函數(aggregate functions such as COUNT, SUM, AVG, MIN, or MAX.)聯合使用來得到一個或多個列的結果集。
語法如下:
SELECT column1, column2, ... column_n, aggregate_function (expression)
FROM tables
WHERE predicates
GROUP BY column1, column2, ... column_n;
舉例
比如說我們有一個學生表格(student),包含學號(id),課程(course),分數(score)等等多個列,我們想通過查詢得到每個學生選了幾門課程,此時我們就可以聯合使用COUNT函數與GROUP BY語句來得到這一結果
SELECT id, COUNT(course) as numcourse
FROM student
GROUP BY id
因為我們是使用學號來進行分組的,這樣COUNT函數就是在以學號分組的前提下來實現的,通過COUNT(course)就可以計算每一個學號對應的課程數。
注意
因為聚合函數通過作用於一組數據而只返回一個單個值,因此,在SELECT語句中出現的元素要么為一個聚合函數的輸入值,要么為GROUP BY語句的參數,否則會出錯。
例如,對於上面提到的表格,我們做一個這樣的查詢:
SELECT id, COUNT(course) as numcourse, score
FROM student
GROUP BY id
此時查詢便會出錯,錯誤提示如下:
Column ‘student.score' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
出現以上錯誤的原因是因為一個學生id對應多個分數,如果我們簡單的在SELECT語句中寫上score,則無法判斷應該輸出哪一個分數。如果想用score作為select語句的參數可以將它用作一個聚合函數的輸入值,如下例,我們可以得到每個學生所選的課程門數以及每個學生的平均分數:
SELECT id, COUNT(course) as numcourse, AVG(score) as avgscore
FROM student
GROUP BY id
二、HAVING
HAVING語句通常與GROUP BY語句聯合使用,用來過濾由GROUP BY語句返回的記錄集。
HAVING語句的存在彌補了WHERE關鍵字不能與聚合函數聯合使用的不足。
語法:
SELECT column1, column2, ... column_n, aggregate_function (expression)
FROM tables
WHERE predicates
GROUP BY column1, column2, ... column_n
HAVING condition1 ... condition_n;
同樣使用本文中的學生表格,如果想查詢平均分高於80分的學生記錄可以這樣寫:
SELECT id, COUNT(course) as numcourse, AVG(score) as avgscore
FROM student
GROUP BY id
HAVING AVG(score)>=80;
在這里,如果用WHERE代替HAVING就會出錯
SQL中group by詳解
看一下測試表test
對這個表寫group by
時,可能就會發生下面這樣的怪事:
select name from test group by name -- ok select * from test group by name --error select name,sum(number) from test group by name -- ok
- 1
- 2
- 3
行吧,接下來一步步的來看。
1. 單列group by
對 test表(表1)執行下面語句
select name from test group by name
- 1
結果很明顯,這是表2
為了能夠更好的理解“group by”多個列“和”聚合函數“的應用,由表1到表2的過程中,增加一個虛構的中間表:虛擬表3。下面說說如何來思考上面SQL語句執行情況:
-
from test:sql執行的第一步,找表,這個沒啥變化;
-
from test group by name:沒有join 和 where 操作,就是group by了,這時候的過程就如下圖所示了,找到name那一列,將具有相同name值的行,合並成同一行。比如nama = aa時,就將<1,aa,2>和<2,aa,3>這兩行合並,其它字段(id,number)合並在一個單元格;
-
接下來就對產生的虛擬表3進行select操作了,這時候就可以看出上面的幾句select的問題出在哪了。
(1)直接 select name 是沒問題的,因為group by 的字段就是name,每個單元格只有一個name,某悶忒;
(2)執行 select * 的話,就是從表3中選擇,可是id 和 number 字段中的單元格里的內容有多個值,關系型數據庫是不允許這樣的,這樣就無法形成嚴格的關系約束條件了,所以會報錯;
那么,對於 id 和 number列咋辦呢?聚合函數。
不知道大家有沒有遇到過 aggregator blah blah 之類的報錯,我用 group by 的時候就放過這個錯,現在想來應該就是 后面用了 group by,卻沒對字段進行聚合,導致單元格里有多個值。
聚合函數,就是用來輸入多個數據,輸出一個數據的,如count(id), sum(number),每個聚合函數的輸入就是每一個多數據的單元格。
因此,這里可以執行
select name,sum(number) from test group by name
- 1
那么sum 函數就是對虛擬表3中,每個name對應的number單元格進行sum操作,就可以得到:
2. 對多列進行 group by
那要是group by 多個字段怎么理解呢, 比如還是在test 表中,group by name,number
,此時我們可以將name 和 number 看成一個整體字段,將其作為一個整體來進行判斷划分的。如圖:
這里只有 <bb, 5>和<cc, 6>是 name 和 number 都相等的,所以將其進行合並,其余並不完全一樣,所以沒有進行分組合並。
此時執行以下語句
select name,sum(id) from test group by name,number
- 1
就可以得到
SQL Count(*)函數,GROUP_By,Having的聯合使用
COUNT(*) 函數返回在給定的選擇中被選的行數。
語法:SELECT COUNT(*) FROM table
使用:現在有一個表,名叫app_category,從Navicat中可以看到表中所有數據,如圖所示,可見表中有297條數據
使用count函數的時候可以看到:
當然僅僅是這個樣子,是木有意義的,我用個可視化工具一眼看穿,要這個函數就顯得雞肋了,那么我們繼續往下看。
場景是這樣的:表app_category與表category關聯。且表間關系是一對多,即同一個app_category_id 對應多個category-id,現在我需要統計出每一個category_id在app_category表中出現的次數那么該如何實現呢,請看接下來的操作:
這樣依然有點不夠酷炫,那么我們還可以在后面繼續追加sql語句呀
例如這條語句:
SELECT category_id ,COUNT(*) AS count FROM app_category
GROUP BY category_id HAVING count(category_id) >2
其查詢的結果是只有count的值大於2 的時候,才是需要的結果