06分組統計查詢
分組函式:
統計函式COUNT()/SUM()/MIN()/MAX()/AVG()
例:
SLEECT COUNT(*) 人數, SUM(sal) 總薪資,MIN(sal)最低薪資,MAX(sal)最高薪資,AVG(sal)平均薪資 FROM emp;
COUNT()函式有三種表現形式:
COUNT(*):可以返回表中所有的記錄數
COUNT(欄位):統計不為空的所有資料
COUNT(DISTINCT 欄位):消除重複資料的結果
select語句中每一個限定都是有執行順序的:下面的1、2、3、4、5符號代表執行順序。
4 select (distinct) 列名【別名】,列名【別名】,,。。。
1 from 表名【別名】
2【Where 條件限定】;
3 GROUP BY
HAVING 字句(必須跟GROUP BY一起出現),where是在GROUP BY之前執行的,所以where是不能跟統計函式的;所以用HAVING在GROUP BY之後做條件篩選,直接使用統計函式;
5 ORDER BY 列名 ASC/DESC
--from先執行,再到where,到group by,到select,最後是order by
例:
SELECT job,count(*),min(sal),max(sal)
FROM emp
GROUP BY job;
GROUP BY約定條件:
1.如果查詢不使用GROUP BY子句,那麼SELECT字句只允許出現統計函式,其他任何欄位不允許出現。
例SELECT empno,COUNT(*) FROM emp;這是錯誤的。因為這裡沒有group by子句,
2.如果查詢使用了GROUP BY子句,那麼SELECT子句只允許出現統計函式、分組欄位,其他任何欄位都不允許出現;
例SELECT empno,job,COUNT(*) FROM emp GROUP BY job;是錯誤的;
--這裡的分組欄位是job,所以select字句只允許出現統計函式和job;
3.如果查詢使用了巢狀函式,那麼SELECT子句只允許出現巢狀函式,不允許出現任何欄位包括分組欄位。
例:查詢每個部門的編號、名稱、位置、部門人數、平均工資
資料表:
-dept:編號、名稱、位置
-emp:統計資料:部門人數、平均工資
確定已知關聯欄位:
-僱員與部門:emp.deptno=dept.deptno;
1.查詢部門的編號、名稱、位置、部門人數用僱員編號(count())、工資(AVG())
SELECT d.deptno,d.dname,d.loc,e.empno,e.sal
FROM emp e,dept d
WHERE e.deptno(+)=d.deptno;
2.發現三個重複d.deptno,d.dname,d.loc
SELECT d.deptno,d.dname,d.loc,COUNT(e.empno),AVG(e.sal) --只能出現分組欄位d.deptno,d.dname,d.loc
FROM emp e,dept d
WHERE e.deptno(+)=d.deptno
GROUP BY d.deptno,d.dname,d.loc;
HAVING 字句
例:查詢出每個職位的名稱、平均工資,但是要求職位的平均工資高於2000
如果用以下程式碼是錯誤的:
SELECT job,AVG(sal)
FROM emp
WHERE AVG(sal)>2000(主要是因為WHERE字句不能直接使用統計函式,因為統計函式是在分組函式執行後才出現的,這樣的話按照資料庫執行順序會先執行WHERE後執行GROUP BY,但是此時WHERE還不能使用統計函式;HAVING可以直接使用統計函式;
GROUP BY job;
應改為:
SELECT job,AVG(sal)
FROM emp
GROUP BY job
HAVING AVG(sal)>2000;
範例:
1.顯示所有非銷售人員的工作名稱以及從事同一工作的僱員的月工資的總和;並且要求滿足從事同一工作月工資的合計大於5000,顯示的結果按照月工作的合計的升序排列;
SELECT job,SUM(sal)
FROM emp
WHERE job<>'salesman'
GROUP BY job
HAVING SUM(sal)>5000
ORDER BY SUM(sal) ASC;
2.統計所有銷售人員(領取佣金)和非銷售人員(不領取佣金)的平均工資和人數;
-先統計領取佣金的
SELECT COUNT(*),AVG(sal)
FROM emp
WHERE comm IS NOT NULL;
-統計不領取佣金的
SELECT COUNT(*),AVG(sal)
FROM emp
WHERE comm IS NULL;
-最後用UNION連線起來
SELECT COUNT(*),AVG(sal)
FROM emp
WHERE comm IS NOT NULL
UNION
SELECT COUNT(*),AVG(sal)
FROM emp
WHERE comm IS NULL;