1. 程式人生 > 其它 >MySQL資料庫入門(七)多表查詢及大量練習

MySQL資料庫入門(七)多表查詢及大量練習

技術標籤:Pythonmysql

建表與資料準備

create database day4;
use day4;
# 建表
create table department(
    id int unsigned not null unique,
    name char(20)
    );

create table employee(
    id int unsigned primary key auto_increment,
    name char(12) not null,
    gender enum('male','female') not null default
'male', age int unsigned, dep_id int unsigned not null ); # 寫入資料 insert into department values (100,'技術'), (101,'人事'), (102,'銷售'), (103,'運營'); # 免責宣告:以下名字均是faker name生成的,請勿對號入座。 insert into employee(name,gender,age,dep_id) values ('唐建華','male',18,100), ('黃淑珍','female'
,48,101), ('李暢','male',38,101), ('華桂珍','female',28,102), ('鍾濤','male',18,100), ('廖婷婷','female',18,104);

連表

不加條件的連表就是笛卡爾積,案例如下:

select *
    from employee,department;

這樣生成了24條記錄,即左表6條×右表4條。這種連表方式極少用到,因為這樣生成太多冗餘資料。
內聯表相當於加了where條件的笛卡爾積:

select * from employee,department where employee.
dep_id=department.id;

常用的連表方式是根據某個共同欄位將兩個表進行連表,一共有以下四種類型:

一、內連表

語法案例:

select *
    from department
    inner join employee
    on department.id=employee.dep_id;

執行結果:

+-----+--------+----+-----------+--------+------+--------+
| id  | name   | id | name      | gender | age  | dep_id |
+-----+--------+----+-----------+--------+------+--------+
| 100 | 技術   |  1 | 唐建華    | male   |   18 |    100 |
| 101 | 人事   |  2 | 黃淑珍    | female |   48 |    101 |
| 101 | 人事   |  3 | 李暢      | male   |   38 |    101 |
| 102 | 銷售   |  4 | 華桂珍    | female |   28 |    102 |
| 100 | 技術   |  5 | 鍾濤      | male   |   18 |    100 |
+-----+--------+----+-----------+--------+------+--------+

注意事項:
內連表會捨棄左表和右表兩邊不匹配的資料!
請認真看department表,這裡有4個部門;employee表,這裡有6個員工。
連表以後只有5條記錄,其中department表中“運營”記錄被捨棄,employee表中’廖婷婷’記錄被捨棄。

二、左外表

語法案例:

select *
    from department
    left join employee
    on department.id=employee.dep_id;

執行結果:

+-----+--------+------+-----------+--------+------+--------+
| id  | name   | id   | name      | gender | age  | dep_id |
+-----+--------+------+-----------+--------+------+--------+
| 100 | 技術   |    5 | 鍾濤      | male   |   18 |    100 |
| 100 | 技術   |    1 | 唐建華    | male   |   18 |    100 |
| 101 | 人事   |    3 | 李暢      | male   |   38 |    101 |
| 101 | 人事   |    2 | 黃淑珍    | female |   48 |    101 |
| 102 | 銷售   |    4 | 華桂珍    | female |   28 |    102 |
| 103 | 運營   | NULL | NULL      | NULL   | NULL |   NULL |
+-----+--------+------+-----------+--------+------+--------+

注意事項:
左外表會保留左表全部資料,捨棄右表不匹配的資料!
請認真看department表,這裡有4個部門;employee表,這裡有6個員工。
連表以後只有6條記錄,其中department表中的4條記錄齊全,employee表中’廖婷婷’記錄被捨棄。

三、右外連表

語法案例:

select *
    from department
    right join employee
    on department.id=employee.dep_id;

執行結果:

+------+--------+----+-----------+--------+------+--------+
| id   | name   | id | name      | gender | age  | dep_id |
+------+--------+----+-----------+--------+------+--------+
|  100 | 技術   |  1 | 唐建華    | male   |   18 |    100 |
|  101 | 人事   |  2 | 黃淑珍    | female |   48 |    101 |
|  101 | 人事   |  3 | 李暢      | male   |   38 |    101 |
|  102 | 銷售   |  4 | 華桂珍    | female |   28 |    102 |
|  100 | 技術   |  5 | 鍾濤      | male   |   18 |    100 |
| NULL | NULL   |  6 | 廖婷婷    | female |   18 |    104 |
+------+--------+----+-----------+--------+------+--------+

注意事項:
右外表會保留右表全部資料,捨棄左表不匹配的資料!
請認真看department表,這裡有4個部門;employee表,這裡有6個員工。
連表以後只有6條記錄,其中department表中“運營”記錄被捨棄,employee表中6條記錄齊全。

四、全外連表

語法案例:
mysql不支援全外連表,但是可以使用union變通實現全外連表,程式碼如下:

select *
    from department
    left join employee
    on department.id=employee.dep_id
union
    select *
        from department
        right join employee
        on department.id=employee.dep_id;

執行結果:

+------+--------+------+-----------+--------+------+--------+
| id   | name   | id   | name      | gender | age  | dep_id |
+------+--------+------+-----------+--------+------+--------+
|  100 | 技術   |    5 | 鍾濤      | male   |   18 |    100 |
|  100 | 技術   |    1 | 唐建華    | male   |   18 |    100 |
|  101 | 人事   |    3 | 李暢      | male   |   38 |    101 |
|  101 | 人事   |    2 | 黃淑珍    | female |   48 |    101 |
|  102 | 銷售   |    4 | 華桂珍    | female |   28 |    102 |
|  103 | 運營   | NULL | NULL      | NULL   | NULL |   NULL |
| NULL | NULL   |    6 | 廖婷婷    | female |   18 |    104 |
+------+--------+------+-----------+--------+------+--------+

注意事項:
全外連表不會捨棄任何資料!
請認真看department表,這裡有4個部門;employee表,這裡有6個員工。

連表練習

  1. 查詢所有人事部的員工名單:
select e.name 姓名
    from department d  # 部門表重新命名為d
    inner join employee e  #員工表重新命名為e
    on d.id=e.dep_id  # 部門表的id欄位與員工表的dep_id欄位建立內連線
    where d.name='人事';  # 篩選部門名字是'人事'的記錄
  1. 查詢人事部年齡大於40歲的員工名單:
select e.name 姓名
    from department d
    inner join employee e
    on d.id=e.dep_id
    where d.name="人事" and e.age>40;  # 篩選部門名字是人事且員工年齡大於40歲的記錄
  1. 查詢年齡大於20歲的員工及所在部門:
select e.name 姓名,d.name 部門
    from department d
    inner join employee e
    on d.id=e.dep_id
    where age>20;
  1. 查詢所有部門的名字和員工人數:
select d.name 部門,count(e.id) 人數
    from department d
    left join employee e
    on d.id=e.dep_id
    group by d.name;  # 按部門名字進行分組

注意:這裡要用左外連表,因為所有的部門資料都要保留,不能遺漏沒人的部門。
5. 查詢所有部門的名字和員工人數,按人數從高到低排列:

select d.name 部門,count(e.id) 人數
    from department d
    left join employee e
    on d.id=e.dep_id
    group by d.name
    order by 人數 desc;  # 按人數從高到低排序

子查詢

子查詢是指查詢中巢狀查詢。
具體看下列案例:

  1. 查詢平均年齡在25歲以上的部門:
select d.name 部門
    from department d
    where id in(  # 篩選部門id在平均年齡25歲以上的
        select dep_id
            from employee
            group by dep_id  # 按部門id分組
            having avg(age)>25  # 按平均年齡過濾部門,只保留平均年齡大於25的
        );
  1. 查詢不足1人的部門名(子查詢得到的是有人的部門id)
select name
    from department d
    where d.id not in(
        select dep_id from employee
            group by dep_id
            having count(id)>=1
        );  # 這種寫法適用性更廣,若將1改成2可找出人數僅1人或不足1人的部門
  1. 查詢大於單位平均年齡的員工
select name,age
    from employee
    where age>(  # 括號內子句中計算單位的平均年齡
        select avg(age)
            from employee
        );

多表查詢總結:

  1. 遇到既可使用子查詢實現也可使用連表查詢實現的情況,優先考慮使用連表查詢,因為連表查詢效率比子查詢高。
  2. 寫多表查詢程式碼時要分層分步實現,每一步經過驗證無誤後,再將若干步驟拼接起來。
  3. 注重書寫格式,建議參考上述案例中select父句和子句縮排書寫格式,既可以方便書寫註釋又方便識別父句與子句,大大提高程式碼可讀性。
  4. 注意select語句的子句執行順序,請參照子句執行的順序書寫子句。
    在這裡插入圖片描述