Oracle基礎學習二之統計函數及分組查詢


統計函數及分組查詢
 1、統計函數
   在之前曾看過count()函數,此函數功能可以統計表中的數據量,實際上這個也是一個統計函數,且常用的統計 函數 有如下幾個:
   .Count():查詢表中的數據記錄;
   .Avg():求出平均值;
   .Sum(): 求出;
   .Max():求出最大值;
   .Min():求出最小值;
范例:測試Count/avg/sum函數
  .統計出公司的所有雇員,每個月支付的平均工資和總工資.
   select count(empNo), sum(sal), avg(sal) from emp;
   select max(sal), min(sal) from emp;
注意點:關於Count()函數
   count函數的主要功能是進行數據的統計,但是在進行數據統計的時候,如果一張表中沒有統計記錄,count()也會返回結果,只是這個數據是“0”。
   select count(eName) from bonus;
如果使用的是其他函數,則有可能返回null,但是count永遠都會返回一個具體的數字,這一點以后在開發之中都有用。
 2、分組統計
   在對分組之前必須明確一點,什么情況下可能分組,例如:.公司的所有雇員,要求男性一組,女性一組,之后可以統計男性和女性的數量;
      .按照年齡分組,18歲以上的分一組,18以下的分一組;
      .按照地區分組:北京一組,上海一組,四川一組;
這些信息如果都保存在了數據庫中,肯定在數據的某一列上會存在重復的內容,例如:在性別分組的時候,性別肯定有重復,按照年齡分組(有一個范圍重復),按照地區分組有一個地區的信息重復。
 所有分組之中有一個不成文的規定:當數據重復的時候分組才有意義,分組的關鍵字是Group by子句完成,此時sql語法如下:select [distinct] *|分組字段1[別名][,分組字段2[別名],...]|統計函數
  from 表名稱[別名] [,表名稱[別名],...]
  [where 條件(s)]
  [Group by 分組字段1[分組字段2,...]
  [Order by 排序字段 Asc|Desc [,排序字段 Asc|desc,..]
  范例:按照部門編號分組,求出每個部門的人數,平均工資。
  select deptNO count(empNo), avg(sal)
  from emp
  Group by deptNo;
但是現在一旦分組后,實際上對於語法上就會出現了新的限制,對於分組以下要求:
  .分組函數可以在沒有分組的時候單獨使用,可是卻不能出現其他查詢字段。
  select count(empNo) from emp;這樣可以
  select empNo ,count(empNo) from emp 錯誤
還可以:select job, count(empNo), from emp
        group by job;正確(驗證了不能出現其他查詢字段)
  .分組函數允許嵌套,但是嵌套之后的分組函數的查詢之中不能出現任何的其他字段。
  范例:按照職位分組,統計平均工資最高的工資
     select 這里不能出現其他字段的查詢 max(avg(sal)) from emp group by job;
  .如果現在要分組的話,則select子句之后,只能出現分組的字段和統計函數,其他的字段不能出現;
    select job, count(empNo),avg(sal)
    from emp  group by job;
  范例:查詢每個部門的名稱、位置、部門的人數、平均工資
    select d.dName,e.empno, e.sal
    from dept d, emp e
    where d.deptNo=e.deptNo
    按照上述查詢結果中,可以發現在dname字段上顯示除了重復的數據,按照之前對分組的理解,只要數據重復了,那么就有可能進行分組的查詢操作,但是此時與之前的分組不太一樣,之前的分組是針對於一張實體表進行的分組(emp,dept都屬於實體表),但是對於以上的數據是通過查詢結果顯示的,是一張臨時的虛擬表,但是不管是否是實體表還是虛擬表,只要有重復,那么直接進行分組。
    select d.dname,count(e.empno),NVL(avg(e.sal), 0)
    from dept d, emp e
    where d.deptno= e.deptno(+)
    group by d.dname;
    之前的所有操作都是針對於單子段分組的,而實際上分組操作之中也可以是多字段分組。(多/單前提是要重復)
    范例:select d.deptno,d.dname, d.loc, count(e.empno), NVL(avg(e.sal), 0)
          from dept d, emp e
          where d.deptno=e.deptno(+)
          group by d.deptno, d.dname, d.loc;  
    范例:要求統計出每個部門的詳細信息,並且要求這些部門的平均工資高於2000。(之前唯一只有where限定查詢的語法,且where子句不能使用統計函數)
   此時如果要對分組后的數據再次進行過濾,則要使用having子句完成,此時的SQL語法格式如下:
  select [distinct] *|分組字段1[別名][,分組字段2[   別名],...]|統計函數
  from 表名稱[別名] [,表名稱[別名],...]
  [where 條件(s)]
  [Group by 分組字段1[分組字段2,...]
  [Having分組后的過濾條件(可以使用統計函數)]
  [Order by 排序字段 Asc|Desc [,排序字段   Asc|desc,..]
   Select d.deptNO, d.dname,d.loc, count(e.empno) myCount, NVL(avg(e.sal)) mySal
   from dept d, emp e
   where d.deptno=e.deptno(+)
   Group by d.deptno, d.dname, d.loc
   Having avg(sal)>2000;
  總結:where和Having的區別:
  .where:是在執行Group by操作之前進行的過濾,表示從全部數據之中篩選出部分數據,在where中不能使用統計函數;
  .Having:是在group by分組之后的再次過濾,可以在Having子句中使用統計函數;
-------------------------------------------------子查詢
 子查詢=簡單查詢+限定查詢+多表查詢+ 統計查詢的綜合體,多表查詢效率很好,針對小型的數據量是不錯的選擇,大數據量下,多表查詢性能很差,但是最有利的子查詢可以替代多表查詢,實際上在開發中使用這種方式也很多。所謂子查詢就是在一個查詢之中嵌套了其他的查詢,嵌套子查詢之后的查詢SQL語法如下:
select [distinct] *|分組字段1[別名][,分組字段2[     別名],...]|統計函數 (
  select [distinct] *|分組字段1[別名][,分組字段2[   別名],...]|統計函數
  from 表名稱[別名] [,表名稱[別名],...]
  [where 條件(s)]
  [Group by 分組字段1[分組字段2,...]
  [Having分組后的過濾條件(可以使用統計函數)]
  [Order by 排序字段 Asc|Desc [,排序字段       Asc|desc,..] )

from 表名稱[別名] [,表名稱[別名],...] (
  select [distinct] *|分組字段1[別名][,分組字段2[   別名],...]|統計函數
  from 表名稱[別名] [,表名稱[別名],...]
  [where 條件(s)]
  [Group by 分組字段1[分組字段2,...]
  [Having分組后的過濾條件(可以使用統計函數)]
  [Order by 排序字段 Asc|Desc [,排序字段             Asc|desc,..] )
[where 條件(s)] (
  select [distinct] *|分組字段1[別名][,分組字段2[   別名],...]|統計函數
  from 表名稱[別名] [,表名稱[別名],...]
  [where 條件(s)]
  [Group by 分組字段1[分組字段2,...]
  [Having分組后的過濾條件(可以使用統計函數)]
  [Order by 排序字段 Asc|Desc [,排序字段       Asc|desc,..])
[Group by 分組字段1[分組字段2,...]
[Having分組后的過濾條件(可以使用統計函數)]
[Order by 排序字段 Asc|Desc [,排序字段Asc|desc,..]
理論上子查詢可以出現在查詢語句中的任意位置上,但是從個人而言,子查詢出現在where和from子句中較多:
   總結:.where:子查詢一般只返回單行單列、多行單列  、單行多列的數據;
         .from:子查詢返回的一般是多行多列的數據,  當作一張臨時表出現。
   范例:select * from emp
  where (sal, job)=(
  select sal,job from emp
  where ename='ALLEN');返回單行多列的結果
如果現在的子查詢返回的是多行單列數據的話,這個時候就需要使用三種判斷符判斷:IN、ANY、ALL;
1、IN操作符:用於指定一個子查詢的判斷范圍
   這個操作符的使用實際上於前面的IN一樣,唯一不同的是,里面的范圍是由子查詢指定。
   select *  from emp
 where sal IN (
    select sal
    from emp
     where job='MANAGER');
但是在使用IN的時候還要注意NOT IN問題,在子查詢之中,如果一個內容是null,則不會查詢出任何結果。
2、ANY操作符:與每一個內容相匹配,有三種匹配形式
   .=ANY: 功能與IN操作符是完全相同;
          select * from emp
   where sal= any( select sal
                 from emp
                 where job='MANAGER');
   .>ANY: 比子查詢返回的記錄最小的還要大的數據;
   select * from emp
   where sal>any( select sal
                 from emp
                 where job='MANAGER');
   .<ANY: 比子查詢返回的記錄最大的還要小的數據;
   select * from emp
   where sal<any( select sal
                 from emp
                 where job='MANAGER');

3、ALL操作符:與每一個內容相匹配,有兩種形式:
   .>ALL:比子查詢中返回的最大的記錄還要大;
   select * from emp
   where sal<any( select sal
                 from emp
                 where job='MANAGER');
   .<ALL:比子查詢中返回的最小的記錄還要小;
   select * from emp
   where sal<any( select sal
                 from emp
                 where job='MANAGER');
以上的所有子查詢都是Where子句中出現的,下面的是在from子句中出現的子查詢,這個子查詢一般返回的是多行多列的數據,當作一張臨時表的方式來處理。
   范例:查詢出每個部門的編號,名稱,位置,部門人數,平均工資
    第一種方法:多表方法:
    select d.deptno, d.dname,d.loc, count(e.empno), avg(e.sal)
    from emp e, dept d
    where e.deptno(+)=d.deptno
    group by d.deptno,d.dname, d.loc;
    第二種方法:子查詢法:通過子查詢完成,所有的統計查詢只能在Group by中出現,所以在子查詢中負責統計數據,而在外部查詢中,負責將統計數據和dept表數據相統一。
    select d.deptno ,d.dname,d.loc,temp.count,temp.avg
    from dept d,(
        select deptno dno, count(empno) count,  avg(sal) avg
        from emp
        group by deptno) temp
    where d.deptno= temp.dno(+);
    大部分情況下,如果最終的查詢結果之中需要出現select子句,但是又不能直接使用統計函數的時候,就在子查詢中統計信息,即:有復雜統計的地方都需要子查詢。
-------------------------------------------


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM