Several mentality of SAP project customers in private enterprises
阿新 • • 發佈:2021-12-06
12.18
1.多表查詢
#查詢員工名為'Abel'的人在哪裡工作 SELECT * FROM employees WHERE last_name ='Abel'; #得到結果department_id為80 #在departments表中查詢department_id為80的工作地點 SELECT * FROM departments WHERE department_id=80; #得到結果location_id為2500 #在locations表中查詢location_id為2500 SELECT * FROM locations WHERE location_id=2500; #得到city為Oxford #綜上員工名為'Abel'的人在Oxford工作 #進行了三次查詢!
-
Q:可以將多張表寫在一張表上嗎?為什不那麼做?
-
A:可以!防止資料的冗餘。用上述例子來舉例,一個員工有一個部門號department_id,部門表中有部門名字,那麼如果寫在一張表中,相同部門號的員工就會有大段文字重複。或者有的員工沒有部門,則會有null值的存在,又或者有些部門還有員工,則前方會有null值。
last_name department_id department_name zhangsan 1000 Finance lisi 1000 Finance wangwu null null null 1001 Corporate Tax
1.1 多表查詢SQL92
#查詢員工的姓名及其部分名稱
SELECT employee_id,department_id
FROM employees,departments
#如上是錯誤的!每一個employee_id對應了每一個department_id,107*27=2889條資料
#上述錯誤被稱為笛卡爾積的錯誤。
#查詢員工的姓名及其部分名稱 SELECT employee_id,department_name FROM employees,departments WHERE employees.department_id=departments.department_id; #過濾條件為employees表中department_id與departments表中department_id相等
1.1.1怎樣會出現笛卡爾積的錯誤
-
省略多表的查詢條件(或關聯條件)
-
連線條件(或關聯條件)無效
-
所有表中所有行的互相連線
1.1.2 Ambiguous問題
對錶中共有的欄位進行查詢時,必須指明該欄位出自哪一個表
從SQL優化的角度,建議在每個欄位前都指明其出自的表!
SELECT employee_id,department_name,department_id
FROM employees,departments
WHERE employees.department_id=departments.department_id;
#如上是錯誤的,Column 'department_id' in field list is ambiguous
#department_id在是不明確的
SELECT employees.employee_id,departments.department_name,departments.department_id
FROM employees,departments
WHERE employees.department_id=departments.department_id;
1.1.3 表的別名
- 由於要給每個欄位加上欄位的出處,使得SQL語句複雜化,因此建議在SQL語句中給表加上別名
- WHERE中不能使用列的別名,但是可以使用表的別名
- 一旦使用表的別名,在WHERE和SELECT則必須使用別名
SELECT t1.employee_id,t2.department_name,t2.department_id
FROM employees t1,departments t2
WHERE t1.department_id=t2.department_id;
1.2結論
結論:如果有n個表實現多表查詢,則至少要有n-1個條件 。
1.3多表查詢的分類
1.3.1等值連線和非等值連結
- 如名字就可以知道意思
SELECT employee_id,salary,grade_level
FROM employees e,job_grades j
WHERE e.salary BETWEEN j.lowest_sal AND j.highest_sal;
#根據employees表中salary的數值比較job_grades表中的區間來得到job_grades表中的grade_level然後輸出
1.3.2自連線和非自連線
- 自己連結自己就是自連線,多個表中的連線就是非自連線。
#練習:查詢員工id,員工姓名,及其管理者的id和姓名
SELECT emp.employee_id,emp.last_name,man.employee_id,man.last_name
FROM employees emp,employees man
WHERE emp.manager_id=man.employee_id;
#完成自連線
1.3.3自連線和外連線
-
合併具有同一列的兩個以上的表的行,結果集中不包含一個表與另一個表不匹配的行,則稱為內連線
-
如上所寫的內容都是內連線
-
合併具有同一列的兩個以上的表的行,結果集中除了包含一個表與另一個表匹配的行之外,還查詢到了左表或右表中不匹配的行,則稱為外連線。
SELECT emp.employee_id,emp.last_name,man.employee_id,man.last_name
FROM employees emp,employees man
WHERE emp.manager_id=man.employee_id+;
#在MYSQL中不認可SQL92的外連線寫法,即上述寫法會報錯!但是Oracle可以。
在此之前需要先學習SQL99中的多表查詢。
1.4多表查詢SQL99
1.4.1內連線
- 語法其實很簡單,將上述描述FROM中的“,”改為JOIN;將WHERE改為ON。
- JOIN+表名+ON+連線條件!
- 其實內連線用的是INNER JOIN,INNER可以省略!
SELECT t1.employee_id,t2.department_name,t2.department_id
FROM employees t1 JOIN departments t2
ON t1.department_id=t2.department_id;
- 多個條件時,則寫多個JOIN...ON
SELECT last_name,department_name,city
FROM employees e JOIN departments d
ON e.department_id =d.department_id
JOIN locations l
ON d.location_id=l.location_id
1.4.2 外連線
- 將INNER JOIN改為OUTER JOIN
- 左外連線為LEFT OUTER JOIN
- 右外連線為RIGHT OUTER JOIN
- 其中有LEFT或者RIGHT使,OUTER可以省略
#查詢所有員工的last_name,department_name資訊
SELECT last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.department_id = d.department_id;
1.4.3全外連線
- MySQL不支援FULL OUTER JOIN。
1.4.4UNION和UNION ALL
-
UNION和UNION ALL是將兩個結果集合併為一個
-
UNION會對返回的結果集進行去重
-
如果明確知道返回的結果不存在重複資料或者不需要去重的,則儘量使用UNION ALL語句,以提高資料效率
假設A為員工表,B為部門表
-
中圖——內連線
SELECT employee_id,department_name FROM employees e JOIN departments d ON e.department_id = d.department_id;
-
左1——左外連線
SELECT employee_id,department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.department_id;
-
右1——右外連線
SELECT employee_id,department_name FROM employees e RIGHT JOIN departments d ON e.department_id = d.department_id;
-
左2
SELECT employee_id,department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.department_id WHERE d.department_id IS NULL;
-
右2
SELECT employee_id,department_name FROM employees e RIGHT JOIN departments d ON e.department_id = d.department_id WHERE e.department_id IS NULL;
-
左3
#左1圖UNION ALL右2圖 #不要習慣性的加分號! SELECT employee_id,department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.department_id UNION ALL SELECT employee_id,department_name FROM employees e RIGHT JOIN departments d ON e.department_id = d.department_id WHERE e.department_id IS NULL;
-
右3
#左2 UNION ALL 右二 SELECT employee_id,department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.department_id WHERE d.department_id IS NULL UNION ALL SELECT employee_id,department_name FROM employees e RIGHT JOIN departments d ON e.department_id = d.department_id WHERE e.department_id IS NULL;