MySQL之多表查詢(DQL)
笛卡爾集
介紹:
表A有m行,表B有n行,查詢結果是m*n行。
beauty表:
boys表:
如果想查詢女神名稱和對應男神名稱,腫麼辦?
語法:SELECT NAME,boyName FROM beauty,boys;
笛卡爾集的錯誤情況:
SELECT COUNT(*) FROM beauty;假設輸出12行
SELECT COUNT(*) FROM boys;假設輸出4行
最終結果:12*4=48行
產生條件:
1.省略連線條件。
2.連線條件無效。
3.所有表中的所有行互相連線。
解決辦法:
在WHERE加入有效的連線條件。
表的別名
介紹:
1.使用別名可以簡化查詢。
2.使用表名字首可以提高執行效率。
示例:
SELECT bt.id,NAME,boyname FROM beauty bt,boys b WHERE bt.boyfriend_id=b.id ;
區分重複的列名
1.使用表名字首在多個表中區分相同的列。
2.在不同表中具有相同列名的列可以用表的別名加以區分。
3.如果使用了表別名,則在select語句中需要使用表別名代替表名。
4.表別名最多支援32個字元長度,但建議越少越好。
MySQL連線
介紹:
又稱多表查詢,當查詢的欄位來自於多個表時,就會用到連線查詢。
分類:
sql92標準:僅僅支援內連線。
sql99標準【推薦】:支援內連線+外連線(左外和右外)+交叉連線。
功能分類:
內連線:[inner] join on
等值連線
非等值連線
自連線
外連線:
左外連線:left [outer] join on
右外連線:right [outer] join on
全外連線
交叉連線
SQL99語法
介紹:
1999年推出的sql語法。
語法:
SELECT 欄位,...
FROM 表1
【INNER|LEFT OUTER|RIGHT OUTER|CROSS】JOIN 表2 ON 連線條件
【INNER|LEFT OUTER|RIGHT OUTER|CROSS】JOIN 表3 ON 連線條件
【WHERE 篩選條件】
【GROUP BY 分組欄位】
【HAVING 分組後的篩選條件】
【ORDER BY 排序的欄位或表示式】
分類:
內連線:inner
外連線
左外:left【outer】
右外:right【outer】
全外:full【outer】
交叉連線:cross
好處:
語句上,連線條件和篩選條件實現了分離,簡潔明瞭!
內連線(inner)
語法:
SELECT 查詢列表 FROM 表1 別名 INNER JOIN 表2 別名 ON 連線條件;
分類:
等值
非等值
自連線
特點:
1.新增排序、分組、篩選。
2.inner可以省略。
3.篩選條件放在where後面,連線條件放在on後面,提高分離性,便於閱讀。
4.inner join連線和sql92語法中的等值連線效果是一樣的,都是查詢多表的交集。
示例:
#一.等值連線 #案例1:查詢員工名、部門名 SELECT last_name,department_name FROM departments d JOIN employees e ON e.department_id = d.department_id; #案例2:查詢名字中包含e的員工名和工種名(新增篩選) SELECT last_name,job_title FROM employees e INNER JOIN jobs j ON e.job_id=j.job_id WHERE e.last_name LIKE '%e%'; #案例3:查詢部門個數>3的城市名和部門個數(新增分組+篩選) #①查詢每個城市的部門個數 #②在①結果上篩選滿足條件的 SELECT city,COUNT(*) 部門個數 FROM departments d INNER JOIN locations l ON d.location_id=l.location_id GROUP BY city HAVING COUNT(*)>3; #案例4:查詢哪個部門的員工個數>3的部門名和員工個數,並按個數降序(新增排序) #①查詢每個部門的員工個數 SELECT COUNT(*),department_name FROM employees e INNER JOIN departments d ON e.department_id=d.department_id GROUP BY department_name; #②在①結果上篩選員工個數>3的記錄並排序 SELECT COUNT(*) 個數,department_name FROM employees e INNER JOIN departments d ON e.department_id=d.department_id GROUP BY department_name HAVING COUNT(*)>3 ORDER BY COUNT(*) DESC; #案例5:查詢員工名、部門名、工種名,並按部門名降序(新增三表連線) SELECT last_name,department_name,job_title FROM employees e INNER JOIN departments d ON e.department_id=d.department_id INNER JOIN jobs j ON e.job_id = j.job_id ORDER BY department_name DESC; #二.非等值連線 #案例1:查詢員工的工資級別 SELECT salary,job_title FROM employees e JOIN jobs g ON e.salary BETWEEN g.min_salary AND g.max_salary; #案例2:查詢工資級別的個數>20的個數,並且按工資級別降序 SELECT COUNT(*),job_title FROM employees e JOIN jobs g ON e.salary BETWEEN g.min_salary AND g.max_salary GROUP BY job_title HAVING COUNT(*)>20 ORDER BY job_title DESC; #三.自連線 #案例1:查詢員工的名字、上級的名字 SELECT e.last_name,m.last_name FROM employees e JOIN employees m ON e.manager_id= m.employee_id; #案例2:查詢姓名中包含字元k的員工的名字、上級的名字 SELECT e.last_name,m.last_name FROM employees e JOIN employees m ON e.manager_id= m.employee_id WHERE e.last_name LIKE '%k%';
外連線
介紹:
主要用於查詢一個表中有,另一個表沒有的記錄。
分類:
左外:left【outer】
右外:right【outer】
全外:full【outer】
特點:
1.外連線的查詢結果為主表中的所有記錄。
如果從表中有和它匹配的,則顯示匹配的值。
如果從表中沒有和它匹配的,則顯示null。
外連線查詢結果=內連線結果+主表中有而從表沒有的記錄。
2.左外連線,left join左邊的是主表。
右外連線,right join右邊的是主表。
3.左外和右外交換兩個表的順序,可以實現同樣的效果。
4.全外連線=內連線的結果+表1中有但表2沒有的+表2中有但表1沒有的。
示例:
#左外連線 SELECT b.*,bo.* FROM boys bo LEFT OUTER JOIN beauty b ON b.boyfriend_id = bo.id WHERE b.id IS NULL; #案例1:查詢哪個部門沒有員工 #左外 SELECT d.*,e.employee_id FROM departments d LEFT OUTER JOIN employees e ON d.department_id = e.department_id WHERE e.employee_id IS NULL; #右外 SELECT d.*,e.employee_id FROM employees e RIGHT OUTER JOIN departments d ON d.department_id = e.department_id WHERE e.employee_id IS NULL; #全外mysql不支援 SELECT b.*,bo.* FROM beauty b FULL OUTER JOIN boys bo ON b.boyfriend_id = bo.id;
交叉連線
介紹:
一般用來返回連線表的笛卡爾積。
語法:
SELECT 查詢列表 FROM 表1 別名 CROSS JOIN 表2 別名 WHERE子句;
或
SELECT 查詢列表 FROM 表1,表2 WHERE子句;
示例:
#交叉連線 SELECT b.*,bo.* FROM beauty b CROSS JOIN boys bo;
圖解JOIN
SELECT <select_list> FROM A LEFT JOIN B ON A.key=B.key;
SELECT <select_list> FROM A INNER JOIN B ON A.key=B.key;
SELECT <select_list> FROM A RIGHT JOIN B ON A.key=B.key;
SELECT <select_list> FROM A LEFT JOIN B ON A.key=B.key WHERE B.key is null;
SELECT <select_list> FROM A RIGHT JOIN B ON A.key=B.key WHERE A.key is null;
SELECT <select_list> FROM A FULL JOIN B ON A.key=B.key;
SELECT <select_list> FROM A FULL JOIN B ON A.key=B.key WHERE A.key is null OR B.key is null;
案例講解
#1.顯示所有員工的姓名,部門號和部門名稱 SELECT last_name,d.department_id,department_name FROM employees e,departments d WHERE e.department_id = d.department_id; #2.查詢90號部門員工的job_id和90號部門的location_id SELECT job_id,location_id FROM employees e,departments d WHERE e.department_id=d.department_id AND e.department_id=90; #3.選擇所有有獎金的員工的last_name、department_name、location_id、city SELECT last_name, department_name, l.location_id, city FROM employees e,departments d,locations l WHERE e.department_id = d.department_id AND d.location_id=l.location_id AND e.commission_pct IS NOT NULL; #4.選擇city在Toronto工作的員工的last_name、job_id、department_id、department_name SELECT last_name, job_id, d.department_id, department_name FROM employees e,departments d ,locations l WHERE e.department_id = d.department_id AND d.location_id=l.location_id AND city = 'Toronto'; #5.查詢每個工種、每個部門的部門名、工種名和最低工資 SELECT department_name,job_title,MIN(salary) 最低工資 FROM employees e,departments d,jobs j WHERE e.department_id=d.department_id AND e.job_id=j.job_id GROUP BY department_name,job_title; #6.查詢每個國家下的部門個數大於2的國家編號 SELECT country_id,COUNT(*) 部門個數 FROM departments d,locations l WHERE d.location_id=l.location_id GROUP BY country_id HAVING 部門個數>2; #7.選擇指定員工的姓名,員工號,以及他的管理者的姓名和員工號 /* * 結果類似於下面的格式: * employees Emp# manager Mgr# * kochhar 101 king 100 */ SELECT e.last_name employees,e.employee_id "Emp#",m.last_name manager,m.employee_id "Mgr#" FROM employees e,employees m WHERE e.manager_id = m.employee_id AND e.last_name='kochhar'; #8.查詢編號>3的女神的男朋友資訊,如果有則列出詳細,如果沒有,用null填充 SELECT b.id,b.name,bo.* FROM beauty b LEFT OUTER JOIN boys bo ON b.boyfriend_id = bo.id WHERE b.id>3; #9.查詢哪個城市沒有部門 SELECT city FROM departments d RIGHT OUTER JOIN locations l ON d.location_id=l.location_id WHERE d.department_id IS NULL; #10.查詢部門名為SAL或IT的員工資訊 SELECT e.*,d.department_name,d.department_id FROM departments d LEFT JOIN employees e ON d.department_id = e.department_id WHERE d.department_name IN('SAL','IT'); SELECT * FROM departments WHERE department_name IN('SAL','IT');