department | 部門表 |
dept_emp | 部門員工任職期表(按部門&時期) |
dept_manager | 部門經理任職期表(按時期) |
employees | 員工詳情表 |
salaries | 員工薪資表(按時期) |
title | 員工職稱表(按時期) |
選擇員工id為110022,因為他還當過經理,所有五張表都會有
SELECT * FROM dept_emp WHERE emp_no = 110022; SELECT * FROM dept_manager WHERE emp_no = 110022; SELECT * FROM employees WHERE emp_no = 110022; SELECT * FROM titles WHERE emp_no = 110022; SELECT * FROM salaries WHERE emp_no = 110022;
dept_emp
dept_manager
employees
title
salaries
分組統計&排序
統計歷史上各個部門所擁有的員工數量,並降序排序
SELECT dept_no, COUNT(*) AS emp_sum FROM dept_emp GROUP BY dept_no ORDER BY emp_sum DESC
創建視圖
把上面的查詢創建成視圖(執行完語句后記得點刷新,不然看不到)
CREATE VIEW test AS SELECT dept_no, COUNT(*) AS emp_sum FROM dept_emp GROUP BY dept_no ORDER BY emp_sum DESC:
聯結
使用聯結,將創建的視圖test補上部門名稱,使用WHERE聯結兩個表的dept_on變量,這是一種等值聯結/自然聯結,因為dept_on在兩張表都是唯一並且一一對應的。
注意一點,聯結后我們仍希望篩選聯結的變量時,需要指定是哪張表的dept_on,不然系統分不清。
以上為聯結的入門,可以說最常用最簡單的聯結方式,接下來我們將聯結方式進行嘗試,再根據使用場景進行總結。
INNER JOIN
上面的自然聯結(使用WHERE)其實就內部聯結,如下兩句SQL語句效果是一樣。
當需要聯結的兩個聯結鍵都是“唯一的”(內部沒有重復值的意思),便需要使用內部聯結,因為這種情況下是用WHERE和INNER JOIN語句是一樣的,為了方便使用WHERE吧,如果語句賦值還是使用INNER JOIN
SELECT * FROM dept_manager, dept_emp WHERE dept_manager.emp_no = dept_emp.emp_no; SELECT * FROM dept_manager INNER JOIN dept_emp ON dept_manager.emp_no = dept_emp.emp_no;
OUTER JOIN
如果兩個表進行聯結的兩個聯結鍵其中一個是有重復值的,一個是沒有的,而且“有重復的”要比“唯一的”范圍“大”,然后我們用"唯一的"的內容去填補“有重復的”表!
使用LEFT JOIN將departments表中信息將dept_manager補上部門名稱
SELECT dept_manager.*, dept_name FROM dept_manager LEFT JOIN departments ON dept_manager.dept_no = departments.dept_no
使用OUTER JOIN必須加上LEFT或者RIGHT,所以實際並不存在OUTER JOIN,而是存在
LEFT JOIN
RIGHT JOIN
(OUTER可以省略不寫)
總結使用場景其實簡單
內部聯結:兩個表的兩個聯結鍵都是“唯一的”
外部鏈接:兩個聯結鍵一個是“有重復的”,一個是“唯一的”,而且前一個的范圍最好比后一個“大”,我們就可以用“唯一的”信息去填補“有重復的”,沒有對應就留空。
聯結探究
我們來研究下不符合上面使用場景的情況是怎樣的。我們以dept_emp和salaries表中員工號為10010的數據為例,因為剛好emp_no有“重復的”,接下來我們就用emp_no作為聯結鍵。
SELECT * FROM dept_emp WHERE emp_no = 10010; SELECT * FROM salaries WHERE emp_no = 10010;
dept_emp
salaries
使用內部聯結,INNER JOIN和WHERE一起上,結構一致,使用“有重復的”的聯結鍵,產生的結果是笛卡爾積:2*6=12
SELECT * FROM salaries INNER JOIN dept_emp ON salaries.emp_no = dept_emp.emp_no WHERE salaries.emp_no = 10010; SELECT * FROM salaries, dept_emp WHERE salaries.emp_no = dept_emp.emp_no AND salaries.emp_no = 10010;
使用外部鏈接,LEFT和RIGHT都上,結果也和內部聯結相似,只是排序些許不同(不影響)。
SELECT * FROM salaries LEFT JOIN dept_emp ON salaries.emp_no = dept_emp.emp_no WHERE salaries.emp_no = 10010; SELECT * FROM salaries RIGHT JOIN dept_emp ON salaries.emp_no = dept_emp.emp_no WHERE salaries.emp_no = 10010;
聯結多個表
SELECT dept_manager.*, departments.dept_name, employees.first_name FROM dept_manager, departments, employees WHERE dept_manager.dept_no = departments.dept_no AND dept_manager.emp_no = employees.emp_no