1. 程式人生 > >select語句(5)--多表查詢

select語句(5)--多表查詢

第四章:多表查詢
多表查詢,又稱表聯合查詢,即一條sql語句涉及到的表有多張,資料通過特定的連線進行聯合顯示.  
一、笛卡爾積
        在數學中,兩個集合X和Y的笛卡尓積(Cartesian product),又稱直積,表示為X × Y.
        假設集合A={a, b},集合B={0, 1, 2},則兩個集合的笛卡爾積為{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
        在資料庫中,如果直接查詢倆張表,那麼其查詢結果就會產生笛卡爾積
        例如:
        select *
        from s_emp,s_dept;     
二、連線查詢
        為了在多表查詢中避免笛卡爾積的產生,我們可以使用連線查詢來解決這個問題.
        連線查詢分為:
            1.等值連線
            2.不等值連線
            3.外連線
                左外連線
                右外連線
                全連線
            4.自連線     
  1、等值連線
        利用一張表中某列的值和另一張表中某列的值相等的關係,把倆張表連線起來。
        例如:查詢員工的名字、部門編號、部門名字       
 select last_name,dept_id,name from s_emp,s_dept where s_emp.dept_id=s_dept.id; 

         

        為了表述的更加清楚,可以給每張表起別名      
  select se.last_name,se.dept_id,sd.id,sd.name from s_emp se,s_dept sd  where se.dept_id=sd.id; 


   2、不等值連線

        假設資料庫中還有一張工資等級表:salgrade
        工資等級表salgrade:
            gradeName列表示等級名稱
            losal     列表示這個級別的最低工資數
            hisal    列表示這個級別的最高工資數 
        表中的資料類似於下面內容:
        id  salgrade    losal hisal
        1  初級程式設計師   2000  4000
        2  中級程式設計師   4000  6000         
        例如:
        查詢出員工的名字、職位、工資、工資等級名稱        
        SELECT  e.last_name, e.title, e.salray, s.gradeName
        FROM    s_emp e, salgrade s
        WHERE   e.salray BETWEEN s.losal AND s.hisal   
3、外連線
        外連線分為:左外連線 右外連線 全連線
        先分別在倆s_emp和s_dept表中插入新的資料
        特點:新員工tom不在任何部門,新增部門st下面沒有任何員工
        insert into s_emp(id,last_name) values(26,'tom');
        insert into s_dept(id,name) values(60,'st');
        commit; 
        下面sql語句可以把上面插入的資料給刪除掉
        delete from s_emp where id=26;
        delete from s_dept where id=60;
        commit;         
        這個時候再使用等值連線的話,查詢出來的資料就會少,因為新增的員工tom和部門表中的資料連線不上,當然新增的部門st也和員工表中的資料連線不上.那麼這倆條資料都是在等值連線中查詢不出來.  
    3.1 左外連線
        例如:
        查詢所有員工 以及對應的部門的名字,沒有部門的員工也要顯示出來      
        select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id=s_dept.id(+);          
        或者 倆者是等價的        
        select last_name,dept_id,name  
        from s_emp left outer join s_dept
        on s_emp.dept_id=s_dept.id;         
        注意:outer可以省去不寫      
    3.2右外連線
        例如:
        查詢所有員工 以及對應的部門的名字,沒有任何員工的部門也要顯示出來        
select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id(+)=s_dept.id; 

       或者 倆者是等價的    

   select last_name,dept_id,name  
        from s_emp right outer join s_dept
        on s_emp.dept_id=s_dept.id; 
        注意:outer可以省去不寫      
    全連線
        例如:
        查詢所有員工 以及對應的部門的名字,沒有任何員工的部門也要顯示出來,沒有部門的員工也要顯示出來       
 select last_name,dept_id,name ,s_dept.id
        from s_emp full outer join s_dept  
        on s_emp.dept_id=s_dept.id;  
        注意:outer可以省去不寫      
4、自連線
        一張表,自己和自己連線
        例如:
        查詢每個員工的名字以及員工對應的管理者的名字        
select s1.last_name,s2.last_name manager_name
        from s_emp s1,s_emp s2
        where s1.manager_id = s2.id;   
三、對查詢結果集的操作
        如果有倆條sql語句,每一條sql都可以查詢出一個結果,這個被稱之為結果集。那麼我們可以使用下面的關鍵字對倆個結果集進行操作
        union        獲得倆個結果集的並集  
        union all    把倆個結果集 合在一起顯示出來    
        minus        第一個結果集除去第二個結果集和它相同的部分
        intersect    獲得倆個結果集的交集          
    3.1 union  獲得倆個結果集的並集  
        例如:        
select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id=s_dept.id(+)
        union
        select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id(+)=s_dept.id;  
    3.2 union all  把倆個結果集 合在一起顯示出來    
        例如:        
select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id=s_dept.id(+)
        union all
        select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id(+)=s_dept.id; 
    3.3 minus  第一個結果集除去第二個結果集和它相同的部分
        例如:      
  select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id=s_dept.id(+)
        minus
        select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id(+)=s_dept.id; 


         對比倆種情況的結果       
  select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id(+)=s_dept.id
        minus
        select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id=s_dept.id(+);

從上面的對比能夠看出結果的不同,前者是用s_emp表除去s_dept表,而後者是使用s_dept表除去s_emp表。

      3.4  intersect  求倆個結果集的交集      
 select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id=s_dept.id(+)
        intersect
        select last_name,dept_id,name  
        from s_emp,s_dept
        where s_emp.dept_id(+)=s_dept.id; 

交集只顯示具有相同值得部分,也就是不顯示s_emp表中的tom,tom2(沒有部門)和是——dept表中的st,st2(沒有員工)。