mysql的DQL(查詢)——連結查詢
#連結查詢 /*含義:又稱多表查詢,當查詢的欄位來自與多表時,就會用到連線查詢 笛卡爾乘積現象:表1 有m行,表2有n行,結果=m*n行 發生原因:沒有有效的連結條件 如何避免:新增有效的連結條件 分類: 按年代分類: sq192:僅支援內連線 sq199【推薦】:支援外連線、內連線(左外+右外)、交叉連結 按功能分類:內連結:等值連結、非等值連結、自連線 外連結:左外連結、右外連結、全外連結 交叉連結 */ USE girls; /*啟動庫*/ SELECT * FROM beauty; /*遍歷beauty的資料*/ SELECT * FROM boys; /*遍歷boys的資料*/
#例題:查詢表中女性各自的男朋友
SELECT NAME,boyName FROM boys,beauty WHERE beauty.boyfriend_id=boys.id;
#一、sq92標準#壹、等值連結
#1、交集查詢 /*①多表等值連結的結果為多表的交集部分 ②n表連線,至少需要n-1個連線條件 ③多表的順序沒有要求 ④一般需要為表起別名 ⑤可以搭配前面介紹的所有子句使用,比如排序,分組,篩選等*/
--案例:查詢女神對應的男神名 SELECT NAME,boyName FROM boys,beauty WHERE beauty.boyfriend_id=boys.id; --案例: 查詢員工名和對應的部門名 SELECT last_name,department_name FROM employees,departments WHERE employees.`department_id`=departments.department_id;
#2、為表其別名 /*①如果為表起了別名,那麼就只能用別名,不能用表明。 ②表明順序顛倒不影響結果 */
--案例:查詢員工名、工種號、工種名 SELECT last_name,employees.job_id,job_title FROM employees ,jobs /*因為表名的反覆出現,所以建議其簡單的別名AS*/ WHERE employees.job_id=jobs.job_id; /*---------區分重名欄位-----------起別名之後---------提高語句簡潔度------------*/ SELECT e.last_name,e.job_id,j.job_title FROM employees e,jobs j WHERE e.job_id=j.job_id;
#3、無視表的順序
#4、加 篩選
--案例:查詢有獎金的員工名、部門名
SELECT last_name,department_name,commission_pct
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`
AND e.`commission_pct` IS NOT NULL;
--案例:查詢城市名中第二個字元為o的部門名和城市名
SELECT department_name,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
AND city LIKE '_o%';
#5、加 分組
--案例:查詢每個城市的部門個數
SELECT COUNT(*) 部門個數,city
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY city;
--案例:查詢有獎金的每個部門的部門名和部門的領導編號和該部門的最低工資
SELECT department_name ,d.`manager_id`,MIN(salary)
FROM departments d,employees e
WHERE d.`department_id`=e.`department_id`
AND commission_pct IS NOT NULL
GROUP BY department_name,d.`manager_id`;
#6、加排序
--案例:查詢每個工種的工種名和員工的個數,並且按員工個數降序
SELECT job_title,COUNT(*)
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;
#7、三表連線
--案例:查詢員工名、部門名和所在的城市降序
SELECT last_name,department_name,city /*三個表*/
FROM employees e,departments d,locations l /*給三個表起別名*/
WHERE e.`department_id`=d.`department_id` /*連線三個表*/
AND d.`location_id`=l.`location_id`
AND city LIKE 's%' /*新增篩選條件*/
ORDER BY department_name DESC; /*倒序輸出*/
#貳、非等值連結
SELECT *FROM `job_grades`; /*顯示所要新增表格中的內容*/
CREATE TABLE job_grades /*在myemployees資料庫中新增本表格*/ (grade_level VARCHAR(3), /*每執行一遍,則多新增一遍*/ lowest_sal INT, highest_sal INT);
INSERT INTO job_grades VALUES ('A', 1000, 2999);
INSERT INTO job_grades VALUES ('B', 3000, 5999);
INSERT INTO job_grades VALUES('C', 6000, 9999);
INSERT INTO job_grades VALUES('D', 10000, 14999);
INSERT INTO job_grades VALUES('E', 15000, 24999);
INSERT INTO job_grades VALUES('F', 25000, 40000);
--案例:查詢員工的工資和工資級別等於a的
SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.`lowest_sal`AND g.`highest_sal`
AND g.`grade_level`='A';
#叄、自連線
--例題:查詢員工名+編號和上級的領導名+編號
SELECT e.employee_id,e.last_name,m.employee_id,m.last_name
FROM employees e,employees m
WHERE e.`manager_id`=m.`employee_id`
#二、sq99語法
/*語法: select 查詢列表 from 表1 別名 【連線模式】 join 表2 別名 on 連線條件 【where 篩選條件】 【group by 分組】 【having 篩選條件】 【order by 排序列表】 分類: 內連線(*):inner 外連線: 左外(*):left 【outer】 右外(*):right 【outer】 全外:full 【outer】 交叉連結:cross */ #一)內連線 /*語法: select 查詢列表 from 表1 別名 inner join 表2 別名 on 連結條件;
分類: 等值 非等值 自連線
特點:
①新增排序、分組、篩選 ②inner可以省略 ③篩選條件房子啊where後面,連線條件放在on後面,提高分離性,便於閱讀 ④inner join連線和sq92連線中的等值連線效果是一樣的,都是查詢多表的交集 */#1、等值連結
--案例:查詢員工名、部門名
SELECT last_name,department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`=d.`department_id`;
--案例:查詢名字中包含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%';
#二)非等值連線
--案例:查詢員工的工資級別
SELECT salary,grade_level
FROM employees e
JOIN job_grades g
ON e.`salary` BETWEEN g.`lowest_sal`AND g.`highest_sal`;
--案例:查詢工資級別的個數<2的個數,並按工資級別降序
SELECT COUNT(*),grade_level
FROM employees e
JOIN job_grades g
ON e.`salary` BETWEEN g.`lowest_sal`AND g.`highest_sal`
GROUP BY grade_level
HAVING COUNT(*)>2
ORDER BY grade_level DESC;
#三)自連線
--案例:查詢員工的名字、上級的名字
SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m
ON e.`employee_id`=m.`employee_id`;
--案例:查詢姓名中包含字元k的員工的名字、上級的名字
SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m
ON e.`employee_id`=m.`employee_id`
WHERE e.`last_name` LIKE '%k%';
#二、外連線 /*特點: 1、外連線的查詢結果為主表中的所有記錄 如果從表中有和它匹配的,則顯示匹配的值 如果從表中沒有和它匹配的,則顯示null 外連線查詢結果=內連線結果+主表中有而從表沒有的記錄 2、左外連結,left join左邊的是主表 右外連結,right join 右邊的是主表 3、左外和右外交換兩個表的順序,可以實現相同的效果 4、全外連結=內連線的結果+表1中有但表2沒有的+表2中有但表1沒有的 */
--案例:沒有男朋友的女神名(用girls資料表)
SELECT * FROM beauty;
SELECT * FROM boys;
SELECT b.name
FROM beauty b
LEFT OUTER JOIN boys bo
ON b.`boyfriend_id`=bo.`id`
WHERE bo.`id`IS NULL;
--案例:查詢那個部門沒有員工
--左外
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;
--全外
USE girls;
SELECT b.*,bo.*
FROM beauty b /*報錯,因為不支援全外連結(多表共性)*/
FULL OUTER JOIN boys bo
ON b.boyfriend_id=bo.id;
#交叉連結 (girls表)
SELECT b.*,bo.*
FROM beauty b
CROSS JOIN boys bo;
#sq192和sq199 對比功能:sq199支援的較多可讀性:sq199實現 連結條件和篩選條件的分離
john連結的7種情況總結:----全外mysql不支援
--①:查A及A與B相交的
(左外連結)
SELECT <select_list>
FEOM A
LEFT JOLN B
ON A.key=B.key;
--②:查A和B相交的記錄(內連線)
SELECT <select_list>
FEOM A
INNER JOLN B
ON A.key=B.key;
--③:查B及B與A相交的
(右外連結)
SELECT <select_list>
FEOM A
RIGHT JOLN B
ON A.key=B.key;
--④:查A排除A與B相交的
(左外連結)
SELECT <select_list>
FEOM A
LEFT JOLN B
ON A.key=B.key
WHERE B.key IS NULL;
--⑤:兩個表的全部
(全外)
SELECT <select_list>
FEOM A
FULL JOLN B
ON A.key=B.key;
--⑥:兩個表的全部但排除交集
(全外)
SELECT <select_list>
FEOM A
FULL JOLN B
ON A.key=B.key
WHERE A.key is null
OR B.key IS NULL;
--⑦:查B排除B與A相交的
(右外連結)
SELECT <select_list>
FEOM A
RIGHT JOLN B
ON A.key=B.key
WHERE A.key IS NULL;
練習題:
--例題:查詢編號>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;
--例題:查詢那個城市沒有部門
SELECT city
FROM departments d
RIGHT OUTER JOIN locations l
ON d.`location_id`=l.`location_id`
WHERE d.`department_id` IS NULL;
--案例:查詢部門名為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');