1. 程式人生 > >三種子查詢

三種子查詢

3種子查詢
一般1對1連結查詢 連結查詢相當於兩張表有資料相關 且兩張表的資料都要查出來
多對一子查詢  子查詢一般就是一張表為了另外一張表提供條件

1.where條件子查詢
    
    請思考:顯示與SMITH同部門的所有員工? 
    思路:
    1 查詢出SMITH的部門號 
    select deptno from emp WHERE ename = 'SMITH'; 
    2 顯示 
    SELECT * FROM emp WHERE deptno = (select deptno from emp WHERE ename = 'SMITH'); 
    資料庫在執行sql 是從左到右掃描的, 如果有括號的話,括號裡面的先被優先執行。 

    多行子查詢
    多行子查詢指返回多行資料的子查詢 

    請思考:如何查詢和部門10的工作相同的僱員的名字、崗位、工資、部門號 
    SELECT DISTINCT job FROM emp WHERE deptno = 10; 
    SELECT * FROM emp WHERE job IN (SELECT DISTINCT job FROM emp WHERE deptno = 10); 
    (注意:不能用job=..,因為等號=是一對一的) 

     在多行子查詢中使用all操作符
    問題:如何顯示工資比部門30的所有員工的工資高的員工的姓名、工資和部門號? 
    SELECT ename, sal, deptno FROM emp WHERE sal > all (SELECT sal FROM emp WHERE deptno = 30); 
    擴充套件要求: 
    大家想想還有沒有別的查詢方法。 
    SELECT ename, sal, deptno FROM emp WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30); 
    執行效率上, 函式高得多 

    在多行子查詢中使用any操作符
    問題:如何顯示工資比部門30的任意一個員工的工資高的員工姓名、工資和部門號? 
    SELECT ename, sal, deptno FROM emp WHERE sal > ANY (SELECT sal FROM emp WHERE deptno = 30); 
    擴充套件要求: 
    大家想想還有沒有別的查詢方法。 
    SELECT ename, sal, deptno FROM emp WHERE sal > (SELECT min(sal) FROM emp WHERE deptno = 30); 

    多列子查詢
    單行子查詢是指子查詢只返回單列、單行資料,多行子查詢是指返回單列多行資料,都是針對單列而言的,而多列子查詢是指查詢返回多個列資料的子查詢語句。 

    請思考如何查詢與SMITH的部門和崗位完全相同的所有僱員。 
    SELECT deptno, job FROM emp WHERE ename = 'SMITH'; 
    SELECT * FROM emp WHERE (deptno, job) = (SELECT deptno, job FROM emp WHERE ename = 'SMITH'); 

2.在from子句中使用子查詢

    在from子句中使用子查詢
    請思考:如何顯示高於自己部門平均工資的員工的資訊 
    思路: 
    1. 查出各個部門的平均工資和部門號 
    SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno; 
    2. 把上面的查詢結果看做是一張子表 
    SELECT e.ename, e.deptno, e.sal, ds.mysal FROM emp e, (SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno) ds WHERE e.deptno = ds.deptno AND e.sal > ds.mysal; 
    小總結: 
    在這裡需要說明的當在from子句中使用子查詢時,該子查詢會被作為一個檢視來對待,因此叫做內嵌檢視,當在from子句中使用子查詢時,必須給子查詢指定別名。 
    注意:別名不能用as,如:SELECT e.ename, e.deptno, e.sal, ds.mysal FROM emp e, (SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno) as ds WHERE e.deptno = ds.deptno AND e.sal > ds.mysal; 
    在ds前不能加as,否則會報錯  (給表取別名的時候,不能加as;但是給列取別名,是可以加as的) 

3.在返回條件中子查詢 (這個子查詢返回只能有一個值)
    https://www.cnblogs.com/GreenLeaves/p/5818787.html
    下面改變當前隨筆2中的需求,需要顯示Customers表中的每個顧客的訂單總數。

    簡單分析下思路,因為Customers表中沒有訂單總數這個欄位,所以目前我們只能用一個計算欄位來代替訂單總數,而這個計算欄位的列值必須是每個顧客的訂單總數。

    (1)先從Customers表中檢索出顧客列表Id

    (2)對於檢索出來的每個顧客,統計其在Orders表中的訂單數目

    一般情況下統計一個顧客在Orders(訂單表)中的訂單總數,可以這樣做:

    select count(*)  from Orders where CustomerId=1
    上面程式碼統計了顧客編號為1的訂單總數,但是這裡需要統計的是所有使用者的訂單總數,顯然這樣寫不對,我們可以這樣寫:

    select name,(select COUNT(*) from Orders where Orders.CustomerId=Customers.Id) as orders from Customers
    這段程式碼實際並不能檢索出來結果,因為他將一個計算欄位,被插入到其他的SELECT語句中一起被返回,該查詢對對檢索出的每個顧客ID執行一次 select COUNT(*) from Orders where dbo.Orders.CustomerId=當前顧客Id的運算;因為有5個顧客,所以會進行5次運算。返回每個顧客的總訂單數。

    下面是完整程式碼:

    select name,(select COUNT(*) from Orders where Orders.CustomerId=Customers.Id) as orders from Customers
    子查詢中的WHERE子句(where Orders.CustomerId=Customers.Id)與前面使用的WHERE子句稍有不同,因為它使用了完全限定列名,而不只是列名。他指定列名和表名(Orders.CustomerId和Customers.Id),這個Where子句等於告訴SQL比較Orders的CustomerId和當前正從Customers表中檢索的Id