1. 程式人生 > >資料庫:mysql基礎(四)---高階查詢

資料庫:mysql基礎(四)---高階查詢

  • 子查詢(巢狀查詢)

    • 將一個查詢結果作為另一個查詢的條件或者組成繼續進行檢索

    • 分類

      • #先看一個例子
        #查詢20號部門所有員工及其所在部門資訊
        #用關聯查詢來做
         select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 20;
        
        #用子查詢來做
        #先找出來20號部門員工的資訊
        select * from emp where deptno =20;
        #from子句是可以跟表,結果集的,所以我們可以按下面這樣
        select * from (select * from emp where deptno =20) e,dept where e.deptno = dept.deptno;
        
        #再看下面一個例子
        #查詢所有員工及其上級領導(mgr)的名稱(自連線)
        select e1.ename '姓名',e2.ename '領導' from emp e1 left join emp e2 on e1.mgr = e2.empno;
        
        #繼續看下面這個例子
        #查詢編號為7788的員工所在部門的資訊。是否發現什麼不同
        #我們要查詢的結果在一張表內,但是查詢的條件卻在另外一張. 當然我們用關聯查詢也能做出來
        select dept.* from (select * from emp where empno = 7788) e,dept where e.deptno = dept.deptno;
        
        #除了上面這種思路還有其他的麼?其實有一個更為直接的思考方式
        #查詢7788員工的部門編號
        select deptno from emp where empno =7788;        #結果是20
        #根據部門編號查詢部門資訊
        select * from dept where deptno = 20;
        
        #我們結合一下
        select * from dept where deptno = (select deptno from emp where empno =7788); 
        #這種思路,就是找到這些表的關聯欄位.只要我們知道關聯欄位,我們就能查詢了--將條件和結果放到一張表中(查詢通用列)

        其實巢狀查詢就比較符合我們思考方式的一種查詢了.

      •  單行子查詢---子查詢返回結果是一條記錄

        • select * from dept where deptno = (select deptno from emp where empno =7788);返回的就是一條記錄,部門編號

      • 多行子查詢:子查詢返回多條記錄

        • #查詢工資大於2000的員工所在部門資訊。

          • select * from dept where deptno in (select distinct deptno from emp where sal > 2000);

        • 除了in  我們還可以用 any / all

          • =any: 相當於in >any:大於最小值 <any:小於最大值

          • >all:大於最大值 <all:小於最小值

        • 下面是一些小的練習..可以思考一下

      • #查詢工資>20號部門平均工資的員工資訊。
        #子查詢:先找出來20號部門的平均工資
        select avg(sal) from emp where deptno = 20
        select * from emp where sal > (select avg(sal) from emp where deptno = 20);
        
        #查詢工資>20號部門平均工資並且不在20號部門的員工資訊。
        select * from emp where sal > (select avg(sal) from emp w here deptno = 20) and deptno <> 20;
        
        #查詢工資大於所在部門的平均工資的員工資訊。
        #方式1,關聯查詢
        select emp.* from emp,(select deptno,avg(sal) avg from emp group by deptno) e where emp.deptno = e.deptno and sal > e.avg;
        
        #方式2:巢狀查詢
        select * from emp e1 where sal > (select avg(sal) from emp e2 where e2.deptno = e1.deptno);
        
        #最後一題用巢狀方式查詢的執行過程:
        #主查詢將deptno傳給子查詢
        #子查詢根據主查詢的deptno查詢指定部門的平均工資
        #子查詢將該部門平均工資返回給主查詢
        #主查詢根據返回結果進行最後檢索。
      •  下面看一下前面做過的題

      • #查詢20號部門以及工資>2000的員工資訊。
        select * from dept where deptno in (select deptno from emp where sal > 2000);
        
        #上面的一個細節:就是主查詢要的是一個deptno,所以子查詢就要返回一個deptno
        #如果子查詢返回的是deptno,dname的話,那麼就會報錯了.如果子查詢返回的結果不是一個,但是主查詢所需條件只能一個,那怎麼做呢?
        
        #有沒有這樣一種方式,我們不關心子查詢返回了多少個結果,而只是去想辦法讓主查詢中的條件能在子查詢返回的結果中找到呢?引出了下面的關鍵字 exists.
        
        #exists 就是不關心子查詢你到底返回了多少個欄位,只是關心你返回的所有欄位中有沒有我需要的欄位.
        #下面說一下這道題應用exists的解法
        
        select * from dept where exists (select * from emp where sal > 2000 and emp.deptno = dept.deptno);
        
        
      •  in和exists的區別

        • in先執行子查詢,將查詢得到的結果整理完畢返回給主查詢,主查詢再根據條件在子查詢返回的結果中查詢,exists先執行主查詢,把值交給子查詢,依次去匹配
        • in需要關注子查詢返回值的欄位資訊;exists不需要關係返回欄位
        • exsts將主查詢的記錄依次在子查詢匹配,如果匹配返回true並展示
    • 那麼我們什麼時候用關聯查詢,什麼時候使用子查詢呢?

      • 如果我們查詢的結果存在於多張表的時候,使用關聯查詢較好
      • 如果結果分佈在一張表的時候,子查詢較好
      • 效率上的差異:關聯查詢是將多張表關聯在一起,資源佔用上稍微高一點;子查詢資源的消耗稍微小一點,但是它可能存在多次查詢