1. 程式人生 > >Mysql 連線查詢

Mysql 連線查詢

連線查詢

  • 含義:又稱多表查詢,當查詢的欄位來自於多個表時,就會用到連線查詢
  • 笛卡爾乘積現象:表1 有m行,表2有n行,結果=m*n行
    • 發生原因:沒有有效的連線條件
    • 如何避免:新增有效的連線條件
  • 分類:
    • 按年代分類:

      • sql92標準:僅僅支援內連線
      • sql99標準【推薦】:支援內連線+外連線(左外和右外)+交叉連線
    • 按功能分類:

      • 內連線:

        • 等值連線
        • 非等值連線
        • 自連線
      • 外連線:

        • 左外連線
        • 右外連線
        • 全外連線
      • 交叉連線

1 sql92標準

1.1 等值連線

  • ① 多表等值連線的結果為多表的交集部分
  • ②n表連線,至少需要n-1個連線條件
  • ③ 多表的順序沒有要求
  • ④一般需要為表起別名
  • ⑤可以搭配子句使用,比如排序、分組、篩選
#1.簡單例子
#案例1:查詢女孩和對應的男孩
SELECT NAME,boyName 
FROM
boys,beauty WHERE beauty.boyfriend_id= boys.id; #案例2:查詢員工名和對應的部門名 SELECT last_name,department_name FROM employees,departments WHERE employees.department_id=departments.department_id; #2、為表起別名 /* ①提高語句的簡潔度 ②區分多個重名的欄位 注意:如果為表起了別名,則查詢的欄位就不能使用原來的表名去限定 */ #查詢員工名、工種號、工種名 SELECT e.last_name,e.job_id,j.job_title FROM
employees e,jobs j WHERE e.job_id=j.job_id; #3、兩個表的順序是否可以調換 #查詢員工名、工種號、工種名 SELECT e.last_name,e.job_id,j.job_title FROM jobs j,employees e WHERE e.job_id=j.job_id; #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; #案例2:查詢城市名中第二個字元為o的部門名和城市名 SELECT department_name,city FROM departments d,locations l WHERE d.location_id = l.location_id AND city LIKE '_o%'; #5、可以加分組 #案例1:查詢每個城市的部門個數 SELECT COUNT(*) 個數,city FROM departments d,locations l WHERE d.location_id=l.location_id GROUP BY city; #案例2:查詢有獎金的每個部門的部門名和部門的領導編號和該部門的最低工資 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;

1.2 非等值連線

#案例1:查詢員工的工資和工資級別

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 salary,employee_id from employees;
select * from job_grades;
CREATE TABLE job_grades
(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);
*/

1.3自連線

#案例:查詢 員工名和上級的名稱
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;

2 sql99標準

  • 語法:
select 查詢列表 from1 別名 【連線型別】join2 別名 on 連線條件【where 篩選條件】【group by 分組】【having 篩選條件】【order by 排序列表】
  • 分類:
    • 內連線(★):inner
    • 外連線
      • 左外(★):left 【outer】
      • 右外(★):right 【outer】
      • 全外:full【outer】
    • 交叉連線:cross

2.1內連線

  • 語法:
select 查詢列表 from1 別名 inner join2 別名 on 連線條件;
  • 分類:
    • 等值
    • 非等值
    • 自連線
  • 特點:
    • ①新增排序、分組、篩選
    • ②inner可以省略
    • ③ 篩選條件放在where後面,連線條件放在on後面,提高分離性,便於閱讀
    • ④inner join連線和sql92語法中的等值連線效果是一樣的,都是查詢多表的交集
#1、等值連線
#案例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;

#二)非等值連線
#查詢員工的工資級別
SELECT salary,grade_level FROM employees e JOIN job_grades g ON e.salary BETWEEN g.lowest_sal AND g.highest_sal;
#查詢工資級別的個數>20的個數,並且按工資級別降序
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(*)>20 ORDER BY grade_level DESC;

#三)自連線
#查詢員工的名字、上級的名字
SELECT e.last_name,m.last_name FROM employees e JOIN employees m ON e.manager_id= m.employee_id;
#查詢姓名中包含字元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%';

2.2 外連線

  • 應用場景:用於查詢一個表中有,另一個表沒有的記錄
  • 特點:
    • 1、外連線的查詢結果為主表中的所有記錄
      • 如果從表中有和它匹配的,則顯示匹配的值
      • 如果從表中沒有和它匹配的,則顯示null
      • 外連線查詢結果=內連線結果+主表中有而從表沒有的記錄
    • 2、左外連線,left join左邊的是主表[右外連線,right join右邊的是主表]
    • 3、左外和右外交換兩個表的順序,可以實現同樣的效果
    • 4、全外連線=內連線的結果+表1中有但表2沒有的+表2中有但表1沒有的
#引入:查詢男朋友 不在男神表的的女神名
SELECT * FROM beauty;
SELECT * FROM boys;
#左外連線
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;
#全外
USE girls;
SELECT b.* ,bo.* FROM beauty b FULL OUTER JOIN boys bo ON b.boyfriend_id = bo.id;
#交叉連線
SELECT b.,bo. FROM beauty b CROSS JOIN boys bo;

3 sql92和 sql99pk

  • 功能:sql99支援的較多
  • 可讀性:sql99實現連線條件和篩選條件的分離,可讀性較高

4 連線查詢總結

連線查詢1

連線查詢2