1. 程式人生 > >Oracle資料庫中的高階查詢以及表連線/內連線/外連線

Oracle資料庫中的高階查詢以及表連線/內連線/外連線

主要針對以下問題進行講解:
1.列別名和表別名
2.select…from where…group by…having…order by…
3.order by 排序 正序,逆序,單列排序,多列排序
4.rownum rowid Oracle的偽列
5.函式:單行函式(日期函式,字元函式,數學函式,轉換函式,其他),多行函式
6.聚合函式(max ,min avg,sum,count)
7.group by 分組
8.having關鍵字

1.列別名和表別名

加類別名

語法: 欄位名 as 欄位別名
select 'dear '||ename from emp;
針對表中欄位的別名稱為列別名

第一種寫法: select 'dear '||ename as 姓名 from emp;
as 是可以省略的
第二種寫法:別名可以加雙引號 select 'dear '||ename “姓名” from emp;
雙引號可以省略
有一種情況雙引號不能省略:別名中有空格,雙引號不能省略

表別名

        語法 : 表名  表別名

–查詢10部門的員工的姓名和工作
select ename,sal,job from emp where deptno=10;
–給emp表一個別名 語法 : 表名 表別名
select e.ename,e.sal,e.job from emp e where e.deptno=10;
select ename,sal,job from emp e where deptno=10; 一張表可以這樣不會出問題,但是多張表後就不可以了。

 --規則:一旦給了表別名後,所有欄位的使用都要:表別名.欄位名
                    --  注意  :表別名是沒有as的

2.select…from where…group by…having…order by…

  注意事項:(1)select ...from...必不可少的
                 eg:select sysdate from dual;
            (2)該語句的執行順序,按照這樣的順序where...group by...having...order by...
            (3)這些關鍵字不能掉換順序,可以沒有,但是如果有的話,是不能掉換順序的

3.order by 排序 正序,逆序,單列排序,多列排序

   單列排序
   
問題:查詢emp表中員工的姓名,工資,按照工資降序排序
select ename,sal from emp order by sal desc;
問題:查詢emp表中員工的姓名,工資,按照工資升序排序
 select ename,sal from emp order by sal asc;
  asc可以省略,預設情況下就是升序排列
  
  --總結:語法結構:select....from...order by 欄位名  asc/desc
          --ASC是升序,desc是降序  如果不寫預設是升序
     問題:查詢部門20的員工的姓名和工資,並且按照工資進行降序排序
     select  ename,sal from emp where deptno=20 order by sal desc;
     
     多列排序
     --問題:查詢emp表中的員工的姓名,部門編號,工資,先按照部門進行升序排列,同部門內部按照工資進行降序排列
      select  ename,deptno,sal from emp where deptno=20 order by deptno asc,sal desc;

多列排序總結:
(1)多列排序語法 order by 欄位名1 asc|desc 欄位名2 asc|desc
(2)多列排序的執行順序,先按照欄位1排序,然後在欄位1排序的基礎上,然後再按照欄位2排序,,,,以此往下

4.rownum rowid Oracle的偽列

rownum

主要是用來做分頁過程(web開發中)**

   select *from emp;
     
     select rownum,emp.*from emp;      (emp.*   別名)
  --rownum 相當於給查詢結果的每一行編一個序列,並沒有儲存在emp表中
     select rownum ,e.* from emp e where deptno=30;                              
            --可以看出rownum是動態變化的
    問題1:查詢emp表的前五條記錄
               select  *from emp where rownum<=5;
         問題2:查詢emp表中的3-5條記錄
               select  *from emp where rownum>=3 and rownum<=5; 這樣是查詢不出來的,因為>在rownum是無法使用的
               select  rownum ro,e.*from emp e where ro>=3 and ro<=5;同樣解決不了。
               
               select  * from(select  rownum ro,e.*from emp e) where ro>=3 and ro<=5;   這樣就可以使用了(子查詢)
                 >   >=符號是是不管用的
  總結:(1)rownum<2   rownum<=2  rownum=1 這樣是可以使用的
                  --不能是rownum>2或者是rownum>=2  rownum=2

–重點

         問題3:查詢emp表中工資最高的前五名的員工姓名,工作,工資
               select ename,job,sal from emp where rownum<=5 order by sal desc;   
                                                        //查詢結果是不正確的,因為只對先進行取前五條,再進行了排序
               
               select *from (select ename,job,sal from emp order by sal desc)x where rownum<=5; 這樣是正確的
         要先排序,再取前五行
         
         問題4:查詢emp表中工資最高的3-5名員工的姓名,工作,工資
--分析   --(1)select  ename ,job,sal from emp order by sal desc   --記為x
            --(2)取x得3-5行:select *from (select rownum ro,x.* from x) where ro>=3 and ro<=5;
            --(3)替換 select *from (select rownum ro,x.* from (select  ename ,job,sal from emp order by sal desc)x) where ro>=3 and ro<=5;

rowid

        **:表示的記錄的實體地址,不隨記錄的在查詢結果中的順序的改變而改變,唯一的且固定的
       --並沒有寫在表結構中**
       select rowid,e.*from emp e;
       
       select rowid ,e.* from emp e where ename='CLARK';

聚合函式(max ,min avg,sum,count)

  問題1:求emp表中員工的總數
  
  select  count(*) from emp;   求記錄的總數
  也可以是這種形式
  select count(empno) from emp;
  
  問題2:求emp表中工資最高的那個員工的工資
  
  select max(SAL) FROM EMP;
  
  問題3:求emp表中工資最低的員工的工資
  
  select min(sal) from emp;
  
  問題4:求該公司員工的平均工資
  select avg(sal) from emp;
  
  問題5:求該公司每個月一個總開支(工資和獎金)
  select sum(sal+comm) from emp;   //此處結果有問題   null和數值不能直接相加
  select sum(sal+nvl(comm,0)) from emp; 

—補充:nvl(comm,0) :判斷comm是否為null 要是null 返回為0,要不是null 返回comm

sum

語法:sum(distinct|all)
引數:all表示對所有的值 (預設),distinct只對不同的值
解釋:求總和

示例:
select sum(distinct sal) from emp;
select sum(all sal) from emp;

avg

語法:avg(distinct|all)
引數:all表示對所有的值 (預設),distinct只對不同的值
解釋:求平均值

示例:
select avg(distinct sal) from emp;
select avg(all sal) from emp;

max

語法:max(distinct|all)

引數:all表示對所有的值 (預設),distinct只對不同的值
解釋:求最大值

示例:
select max(distinct sal) from emp;

min

語法:min(distinct|all)
引數:all表示對所有的值 (預設),distinct只對不同的值
解釋:求最小值

示例:
select min(all sal) from emp;

count

語法:count(distinct|all)

引數:all表示對所有的值 (預設),distinct只對不同的值(相同值只取一次)
解釋:求記錄、資料個數。

示例:
select count(sal) from emp;
select count(distinct sal) from emp;

.group by 分組

  問題1:求emp表中每個部門的員工的總人數,請列出部門的編號和總人數,和平均工資
  
  select deptno,count(*),agv(sal) from emp group by deptno;
  問題2:求部門10的員工的個數,員工的平均工資,請列出部門的編號和總人數,以及平均工資
--group by 使用規則:
         --出現在select後面的欄位,除了聚合函式之外,其他欄位內容必須出現在group by之後
         --如果不按照上述規則寫,報錯,不是單組分組函式,使用會出錯。報錯,不是單組函式或者不是group by表示式

問題3:查詢部門10的員工人數和平均工資
select count(*),avg(sal) from emp where deptno=10;

 --多欄位分組的一個問題

問題4:查詢emp表中每個部門,每個職位的員工人數;

select deptno,job,count(*) from emp group by deptno,job;
–注意:多欄位分組,分組的順序是按照欄位的先後順序來的

問題5:查詢emp表中,每個部門的編號,並且按照部門人數進行降序排序

select deptno,count() from emp group by deptno order by count() desc;

8.having關鍵字,主要是和group連用,並且針對聚合函式條件進行二次條件限定的

問題6:查詢emp表中每個部門的人數,找出人數大於3的部門,並按照總人數降序排列

select deptno,count() from emp group by deptno having count()>3 order by count(*) desc;

注意事項:

注意事項:(1)聚合函式的條件,不能出現在from ,where子句,不能出現在group by 後面,
           聚合函式可以出現在select子句,having子句  order by 子句
              
   (2)where子句中放的是普通條件,不涉及到聚合函式的條件
   (3)having 子句中不能放普通條件,涉及聚合函式的條件

高階查詢2

主要針對以下問題進行說明:
1.表連線(內連線,外連線(左外連線,右外連線,全外連線))
2.表連線:兩表連線,三表連線,四表連線
3.子查詢:單行子查詢,多行子查詢
4.子查詢:any all
5.檢視:什麼是檢視?檢視的作用?怎麼建立和刪除檢視?
6.索引:什麼是索引?索引的作用?怎麼建立合適的索引?建立刪除和維護索引語法?

等值連線

--1.問題:查詢每個員工的部門名稱,列出員工姓名和部門名稱
select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno

–表連線中別名的使用:
為了避免出現“未明確定義列”的錯誤,建議使用表別名.欄位名的方式引用欄位

總結:select…from 表1,表2,表3,… where 連線條件1 and 連線條件2 and …
連線條件:e.deptno=d.deptno等值連線的條件,所以這種連線成為等值連線

不等值連線

非等值連線是指在多個表之間使用非等號連線,查詢在多個表中有非等值關聯關係的資料。非等值連線操作符包括>、>=、<、<=、<>以及between…and、like、in等。

例:查詢每個員工的薪水等級

2. 問題:查詢員工表中,每個員工的工資等級,列出員工姓名,工資和工資等級
select e.ename,e.sal,s.grade from emp e,salgrade s
where e.sal between s.losal and s.hisal;

自連線:

自連線是一種特殊的連線,資料的來源是一個表,即關聯關係來自於單表中的多個列。比如職員表中的經理列,就參照了本表中職員編碼列,即經理也是機構下的職員之一。
自連線是通過將表別名虛擬成兩個表的方式實現,可以是等值的或不等值的連線。
例:查詢每個職員經理的名字以及經理的員工編號

--3. 查詢所有比自己領匯入職早的員工的姓名和上級領導的姓名
select w.ename as 員工姓名,m.ename as 上級領導姓名
from emp w,emp m where w.mgr=m.empno and w.hiredate<m.hiredate;

內連線:

--1.問題:查詢每個員工的部門名稱,列出員工姓名和部門名稱
select e.ename,d.dname from emp e inner join dept d on e.deptno=d.deptno;

–總結:select…from 表1 inner join 表2 on 連線條件 where 查詢條件

–問題:查詢部門10中每個員工的工資等級

select e.ename,s.grade from emp e
inner join salgrade s
on e.sal between s.losal and s.hisal             --連線條件
where e.deptno=10;    --查詢條件

--問題:查詢emp表中部門名稱為ACCOUNTING的員工的姓名,和部門位置

select e.ename,d.loc from emp e,dept d

where e.deptno=d.deptno and d.dname='ACCOUNTING';

select e.ename,d.loc from emp e inner join dept d

on e.deptno=d.deptno

where d.dname='ACCOUNTING';

–查詢高於自己部門平均工資的員工的資訊,列出部門平均工資

--(1)獲得每個部門的平均工資
select deptno,avg(sal) avg_sal from emp group by deptno;   --x

--(2) 將x表和emp表做表連線
select e.*,x.* from emp e,x where e.deptno=x.deptno and e.sal>x.avg_sal;

--(3)替換x

select e.*,x.* from
emp e,(select deptno,avg(sal) avg_sal from emp group by deptno)x
where e.deptno=x.deptno and e.sal>x.avg_sal;

內連線和外連線

針對內連線和外連結,我們通過圖表進行詳細說明

A表(父母表):
在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述