鏈接查詢html
主要分爲內鏈接(等值鏈接,非等值鏈接,自鏈接),外鏈接(左外鏈接,右外鏈接,全外鏈接),交叉鏈接三大類。mysql
sql92標準中: from 表1,表2 ,表3 where 條件1 and 條件2 and 題目條件
sql99標準中: from 表1 join 表2 on 條件1 join 表3 on 條件2 where 題目條件sql
內鏈接:表之間經過某種關係創建鏈接來進行關聯查詢。其中自鏈接是針對自身的兩次表的查詢,必須指定別名來區別查詢時使用哪一次的表數據庫
外鏈接函數
外鏈接主要用於添加 where語句後篩選:(主表中有可是副表中沒有)'s 主表中的對象。不添加where 語句則篩選出:以主表爲主的主副鏈接表優化
select 字段 from table_m left [outer] join table_vice1 on 表間關聯條件1 [left join table_vice2 on 關聯條件2 ...] where condition_clause;#條件語句通常爲 ... is [not] null .
與查詢有關的關鍵字段屬於哪一個表,哪一個表就是主表。code
例如:查詢沒有獎金的員工姓名,此時員工表e就爲主表,獎金錶s爲副表。
SELECT e.e_name FROM e LEFT JOIN s ON e.e_id=s.e_id WHERE s.e_id IS NULL;
htm
right [outer] join 相似同理(主副表位置調換)對象
full [outer] join 全鏈接 :兩表交集(經過內鏈接可實現)+左外鏈接(A主B副)+左外鏈接(B主A副)blog
交叉鏈接:交叉鏈接是笛卡爾積在sql中的實現。 關鍵字:cross join
子查詢(內查詢)
聯合查詢
一些思考點
(1) . group by語句的使用場景。
多表鏈接查詢時,若主查詢的select字段中含有 count, sum, average等聚合函數,以 "查詢每一個部門的員工個數" 爲例:
若count字段做爲外查詢字段而直接顯式存在,須要使用group by 語句呈現分類效果
select d.* ,count(e.department_id) as 員工個數 from departments d left join employees e on e.department_id =d.department_id group by d.department_id; /* count(e.department_id) 不該書寫爲count(d.department_id),也不該書寫爲count(*),二者都會致使本沒有員工的部門員工個數計爲1。應充分理解外鏈接查詢結果的含義,從而理解外查詢count(para)字段中para的不一樣所對應的含義,當para爲「*」時,是計算列數,空值也會計算在內並計爲1,故當要求「沒有員工的部門的員工個數既要正確書寫爲0,又不能省略員工個數爲0的部門(簡單的在e表中按照d_id分類count查詢)」時正確操做應爲:d表爲主 e表爲副 group by(d.department_id) 查詢 count(e.department_id) */
假如無group by 子句,則查詢結果將始終爲單行,無論與count(*)同時查詢的還有什麼字段。如:
或是(不合題,僅做示例):
若count字段做爲子查詢(內查詢)隱式存在
select d.* ,(select count(*) from employees e where e.department_id = d.department_id ) 員工個數 from departments d ;
此時爲內外嵌套,外在表現爲單表查詢。
(2). Exist 子查詢的使用。(未充分理解)
博客園'半壁江山'總結詳細,可供參考 關鍵字: 執行順序&規則,boolean,應用場景,效率。
(3). 如題:查詢各部門工資比所在部門平均工資高的員工的員工號,姓名,薪資
① 第一想法: 內鏈接+where clause 子查詢 關聯三表 ,結果正確,表面也易理解。
select d.department_id , d.department_name ,e.employee_id , e.last_name , e.salary from employees e join departments d on e.department_id = d.department_id where salary > (select avg(salary) from employees em where em.department_id = e.department_id);
② 將各部門的平均工資經過 select 子查詢 命名'建表' ——davg。employees,departments,davg 三表左外鏈接 。
select d.department_id , d.department_name ,e.employee_id , e.last_name , e.salary , davg.a as 該部平均工資 from departments as d left join employees as e on e.department_id = d.department_id left join (select department_id , avg(salary) a from employees group by department_id ) as davg on davg.department_id = d.department_id where e.salary > davg.a order by davg.a,e.salary;
固然由於where語句的限制,某些沒有員工的部門沒有呈現出來。(固然題目也沒有這種要求,可是理論上d爲主表進行 left join 查詢時全部的部門都應該呈現,即便對應的其他表爲皆爲null值)。經過刪除where 限制,並按department_id DESC排列能夠看到實際上三表鏈接後是存在這樣的數據的。
... on davg.department_id = d.department_id order by d.department_id DESC limit 0,50;
Limit [ offset ,] row_count ;
The first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1)
Limit row_count OFFSET offset
③ 固然也能夠省略select 字段中的department_name 字段,從而免去departments表與另外兩表的鏈接。只將e表與davg表(經過select 子查詢命名的各部門平均薪資表)內鏈接或者外鏈接。代碼略。
(4) 如題:查詢平均工資最低的部門信息。
錯解1: 子查詢所構建的表不識別,失效
SELECT d.*, davg.a FROM departments AS d RIGHT JOIN ( SELECT department_id, avg( salary ) a FROM employees WHERE department_id IS NOT NULL GROUP BY department_id ) AS davg ON davg.department_id = d.department_id WHERE davg.a = ( SELECT MIN( davg.a ) FROM davg );
Table 'my_employees.davg' doesn't exist
。正解2: 可使用 order by + limit 的結合語句來實現查詢效果
SELECT d.*, davg.a FROM departments AS d RIGHT JOIN ( SELECT department_id, avg( salary ) a FROM employees WHERE department_id IS NOT NULL GROUP BY department_id ) AS davg ON davg.department_id = d.department_id #內鏈接更簡? ORDER BY davg.a ASC LIMIT 1;# 可修改行數肯定是否最低值只有一個。
該策略一樣適用於: 其餘有關 '最低,最高 '類字眼的查詢 (在此不考慮效率問題)
正解3:複雜嵌套1
SELECT d.* FROM departments d WHERE department_id = ( #此處 '=' 換用 'in' 更好 SELECT davg.department_id FROM ( SELECT department_id, avg(salary) a FROM employees GROUP BY department_id ) AS davg WHERE a = ( SELECT MIN(該部平均工資) FROM (SELECT avg(salary) AS 該部平均工資 FROM employees GROUP BY department_id ) AS davg # 'AS davg' 必須有,語法要求。儘管前面select min(arg)不加davg也OK ) ) # 兩個子查詢字段中的別名‘davg’互不影響,固然若寫成不同更易理解。
此類嵌套查詢解題思路:
①明確各個層次,清晰定義。② 從最內層,最小解題單元開始,逐步完善。③ 耐心,耐心。
疑問:對於mysql中重複出現的語句有沒有相似命名定義方法。
正解4:複雜嵌套2
SELECT d.* FROM departments d WHERE department_id = ( #此處 '=' 換用 'in' 更好 SELECT department_id FROM employees e GROUP BY department_id HAVING AVG(salary) = ( SELECT MIN( a ) FROM ( SELECT AVG(salary) a FROM employees GROUP BY department_id ) AS davg ) )
該解不一樣與正解3的地方在於Having 子句的使用替代了where子查詢嵌套,須要理解的是:
要真正理解group by 子句的所帶來的效果/意義,以及各子句之間的執行順序:
① group by 子句的使用必然與' 需使用聚合類函數的需求'有關(想不出沒有使用聚合類函數的需求仍然使用group by 子句的),但: 並不意味着聚合類函數必定[顯式]出如今select 語句的字段中,它也能夠出如今 having ,where 等子句中(執行順序在它以後的就OK)
② 執行順序:from 子句,join ta_name on cond類 子句 , group by 子句 , having 子句 , where 子句,select 子句 ,order by 子句,limit 子句。
解5 存儲過程?視圖?