1. 程式人生 > 實用技巧 >MySQL之多表查詢(DQL)

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');

測試資料