1. 程式人生 > >四.Oracle聚合函數和內外全連接

四.Oracle聚合函數和內外全連接

卡爾 res 別名 無法 多表連接 入職 自連接 忽略 full join

  1.聚合函數

    同時對一組數據行進行操作,對每組行返回一行輸出結果,叫做分組函數。(將多行數據分成一行或多行,每組行只返回一行結果)

    1.1聚合函數不能出現在where字句中

    1.2常用的聚合函數:

        count: 表示返回滿足條件的總行數,(註:建議用rowid統計總行數,因為它代表唯一的物理地址,或者用唯一標識符(主鍵);)

             使用 * 效率慢,因為它先會去select * from all_tab_cols(字典表)去搜索表有那些列,然後再去分析那個列查詢速度更快

              例:select count(rowid) from emp;統計emp表的總行數

        sum :表示求和

              例:select sum(sal+nvl(comm,0)) from emp;  表示求出薪水加獎金的總和,此處用到了nvl();

        avg :表示求平均數

              例:select avg(sal) from emp;  表示求出平均薪水。

        max :表示求最大值

              例:select max(sal) from emp;  表示求出最高薪水。

        min : 表示求最小值

              例:select min(sal) from emp;  表示求出最低薪水。

  2.Order by 

    Order by :表示對查詢語句進行排序

        例:select job from emp order by job;  表示按工作職位進行排序,默認為升序。

          select job from emp order by job desc;  表示按工作職位進行降序

        如果查詢中包含一個聚合函數,而所選擇的列不在聚合函數中,那麽這些列就必須出現在GROUP BY子句中.(不用聚合函數的列必須出現在group by後)
          例1 :select ename,sex from emp group by sex;(錯,ename沒有用聚合函數,也沒有出現在group by後面,因為將sex分成兩組,但ename有很多,到底輸出那個ename呢?)
          例2: select max(ename),sex from emp group by sex;(對)

  3.Having:字句過濾組

      註意:HAVING子句必須出現在GROUP BY語句中.group by 後的任何語句(包括排序..)都是分完組後才進行結果運算

      例:SELECT deptno,AVG(sal) FROM emp GROUP BY deptno HAVING AVG(sal) > 2000  表示查出月薪大於2000的部門編號及平均月薪。

  4.聚合函數的嵌套:

    聚合函數可以嵌套使用,但這條語句必須是GROUP BY語句.且SELECT子句就只能有這個嵌套聚合函數.(如下例子不能有deptno)

        例:1:求出部門平均月薪的最高值.
            select deptno,max(avg(sal)) from emp group by deptno(錯,首先分組成部門求出各部門的平均月薪,再求出部門最高值,部門有多個,最高值只有一個)
            select max(avg(sal)) from emp group by deptno(對)

        例2:求出部門平均月薪最高的部門編號和平均月薪(子查詢)
            select deptno,avg(sal) from emp group by deptno having avg(sal)=(
                select max(avg(sal)) from emp group by deptno
              )

  5.笛卡爾積:將左邊的一條語句按順序和右邊表的每一條數據依次做交集,最終的結果就是左邊的總條數 * 右邊的總條數

        例:select * from emp,dept; 

      笛卡爾積過濾(將兩張表總相同的列進行條件判斷)

          例:列出dept表中的deptno 等於 emp表中的deptno的所用數據行

          select * from dept d,emp e where d.deptno = e.deptno  --86語法

          select * from emp e inner join dept d on e.deptno = d,deptno  --92語法

      笛卡爾積的用處:實現多表連接,用於多表查詢。

      內連接:    

          如果作為主表的表的某一條記錄和右表的任意一條記錄都無法匹配 不會保留這條表的記錄(必須是條件成立才出結果)
              例:(e.deptno=d.deptno符合這個條件才保留,不符合不保留)

      外連接:

        外連接又分為 左外連接右外連接      

          左外連接(left):  以左表為主表 如果在右表匹配不到任何記錄 會保留主表的記錄
            例:(select * from emp e left join dept d on e.deptno=d.deptno符合這個條件保留,不符合條件的emp(主表)表記錄也會保留)

        

          右外連接(right):以右表為主表 如果在左表匹配不到任何記錄 會保留主表的記錄
            例:(select * from emp e right join dept d on e.deptno=d.deptno符合這個條件保留,不符合條件的dept(主表)表記錄也會保留)

      

      全連接:

          全連接(full)就是將左右外聯的結果取並集
            例:select * from emp e full join dept d on e.deptno=d.deptno(符合條件保留,emp,dept兩個表不符合條件的也全部保留)

      交叉連接:cross join

          語法:SELECT … FROM join_table CROSS JOIN join_table2;
            沒有ON子句和WHERE子句,它返回所有連接表中所有數據行的笛卡爾積。
            其結果集合中的數據行數等於第一個表中符合查詢條件的數據行數乘以第二個表中符合查詢條件的數據行數。
              示例:SELECT * FROM emp CROSS JOIN dept;

    6.學習練習題:

    

現有一分組對抗賽表(team),表中有隊名和組編號(type):
 
中國  A 韓國  A 日本  A 美國  B 巴西  B 荷蘭  B現要通過查詢實現A組和B組進行循環對抗,寫出SELECT語句(交叉連接)
select * from(select * from team where type=A)cross join(select * from team where type=B);


查詢出員工姓名及其所在的部門名
    SELECT ename,dname FROM emp e INNER JOIN dept d ON e.deptno=d.deptno
查詢出月薪大於2000的員工姓名、月薪、受雇日期及其所在的部門名,輸出結果按受雇日期排序
    SELECT ename,sal,hiredate,dname FROM emp INNER JOIN dept ON emp.deptno=dept.deptno WHERE emp.sal>2000 ORDER BY hiredate;
查詢出每個員工的姓名、月薪以及月薪等級
    select ename,sal,grade from emp e INNER JOIN salgrade s on sal between s.loal and s.hisal;
查詢出每個員工的姓名、職位、月薪、部門名稱、部門位置、以及月薪的等級,結果按員工編號排序。
    select ename,job,sal,dname,loc,grade from emp e INNER JOIN dept d ON e.depto=d.deptno INNER JOIN salgrade s ON e.sal between s.losal and s.hisal;

查詢出所有的部門編號、部門名及該部門下的所有員工的姓名
    SELECT dept.deptno,dname,ename FROM dept LEFT JOIN emp ON dept.deptno=emp.deptno;

查詢出每個員工的編號、姓名、職位及它的領導的姓名及職位
自連接:參與連接的表都是同一張表。(通過給表取別名虛擬出)
    SELECT e.empno,e.ename,e.job,m.ename,m.job FROM emp e LEFT JOIN emp m ON e.mgr=m.empno;

以下主要為dept 表和 emp表的練習

--聚合函數
select * from emp
--count()次數裏面最好是rowid唯一快,*不建議使用,全部太慢

select count(rowid) from emp

--求出員工總人數。
select count(rowid)from emp
--求出公司每月要支付的月薪總數。
select sum(sal)from emp
--求出最高月薪、最低月薪。
select max(sal),min(sal) from emp
--求出公司的平均月薪。
select avg(sal) from emp


--group by語句練習
select max(sal),job from emp group by job --如果查詢中包含一個聚合函數,而所選擇的列不在聚合函數中,那麽這些列就必須出現在GROUP BY子句中。(也就是說不用聚合函數的列必須出現在group by後面)

select empno,count(rowid) from emp group by empno

select count(rowid) from emp group by job

select job,sex,count(rowid) from emp group by job,sex

select sum(sal+comm) from emp--任何數字與空值進行計算都為空,這裏不為空是因為組函數會忽略空值

select empno,max(ename) from emp group by empno

select sum(sal+nvl(comm,0)) from emp  

select sum(sal)from emp

select max(avg(sal)) from emp group by deptno

--顯示每個部門的員工數量。
select deptno,count(rowid) from emp group by deptno

--顯示每種職位的名及平均月薪。
select job,avg(sal)from emp group by job
--顯示每年入職的員工數量及年份。
select to_char(hiredate,yyyy),count(rowid)from emp group by to_char(hiredate,yyyy)

--顯示部門平均月薪大於2000的部門編號及平均月薪。(?)
select deptno,avg(sal)from emp group by deptno having avg(sal)>2000

--查詢出不是總裁(PRESIDENT)的職位名以及該職位的員工月薪總和,還要滿足同職位的員工的月薪總和大於4500。輸出結果按月薪的總和降序排列。
select job,sum(sal) from emp where job!=PRESIDENT group by job having sum(sal)>4500 order by sum(sal) desc


--聚合函數嵌套
--求出部門平均月薪的最高值。(嵌套)
select max(avg(sal)) from emp group by deptno

--思考:求出部門平均月薪最高的部門編號和平均月薪(子查詢)
select deptno,avg(sal) from emp group by deptno having avg(sal)=(
  select max(avg(sal))from emp group by deptno
)


select * from emp;
select * from dept;
select * from salgrade;
--笛卡爾積
select * from dept d,emp e where d.deptno=e.deptno and d.dname=研發部;

select * from emp e,dept d where e.deptno=d.deptno --86語法

--內聯:(如果作為主表的表的某一條記錄和右表的任意一條記錄都無法匹配,不會保留主表的記錄)(必須是條件成立才出現結果)
select * from emp e inner join dept d on e.deptno=d.deptno --92語法 

--左外聯(如果作為主表的表的某一條記錄和右表的任意一條記錄都無法匹配,會保留主表的記錄)
select * from emp e left join dept d on e.deptno=d.deptno

--右外聯(right)
select * from emp e right join dept d on e.deptno=d.deptno

--全連接 就是將左右外聯的結果取並集full
select * from emp e full join dept d on e.deptno=d.deptno

--查詢出員工姓名及其所在的部門名
select e.ename,d.dname from emp e inner join dept d on e.deptno=d.deptno

--查詢出月薪大於2000的員工姓名,月薪,受雇日期及其所在的部門名,輸出結果接受雇日期排序
select e.ename,e.sal,e.hiredate,d.dname from emp e inner join dept d on e.deptno=d.deptno 
where e.sal>2000
order by e.hiredate asc


--查詢出每個員工的姓名,月薪以及月薪等級
select e.ename,e.sal,s.grade from emp e inner join salgrade s on e.sal between s.losal and s.hisal


--查詢出每個員工的姓名,職位,月薪,部門名稱,部門位置,以及月薪的等級,結果按員工編號排序

select e.ename,e.job,e.sal,d.dname,d.loc,s.grade from emp e 
                           inner join dept d on e.deptno=d.deptno
                           inner join salgrade s on e.sal between s.losal and s.hisal
                           
                           order by e.deptno asc
                           

--查詢出所有的部門編號、部門名及該部門下的所有員工的姓名。
select d.dname,e.ename from dept d left join emp e on d.deptno=e.deptno


select d.deptno,d.dname,e.ename from dept d inner join emp e on d.deptno=e.deptno

--查詢出每個員工的編號、姓名、職位及它的領導的姓名及職位。
select e.ename,e.empno,e.job,d.ename,d.job from emp e inner join emp d on e.mgr=d.empno;
select e.ename,d.ename from emp e inner join emp d on e.mgr=d.empno;


--查詢出每個員工的姓名、職位、月薪、所屬部門名、月薪等級及其領導的姓名、職位、所屬部門名、月薪等級。

      

四.Oracle聚合函數和內外全連接