MySQL多表查詢詳解

多表查詢

1. 表與表之間的關係

<1> 一對一

  • 用戶表和身份信息表,用戶表是主表
  • 男人表、女人表優化

    create table man(code

    mid int primary key auto_increment,
    mname varchar(32),
    wid int unique

    );排序

    create table woman(ci

    wid int primary key auto_increment,
    wname varchar(32)

    );rem

<2> 一對多

  • 最多見得表關係,用戶表和訂單表
  • 員工表、部門表
    create table emp(數學

    empno int primary key auto_increment,
    ename varchar(32)
    deptno int

    );io

    create teble dept(table

    deptno int primary key auto_increment,
    dname varchar(32)

    );date

<3> 多對多

  • 學生表和課程表,一般狀況都是將多對多的關係拆分爲一對多或者多對一的關係
  • 至少須要三張表select

    create table student(

    cid int primary key auto_increment,
    sname varchar(32)

    );

    insert into student (sname) values('小張');
    insert into student (sname) values('小李');
    insert into student (sname) values('小王');

    create table course(

    sid int primary key auto_increment,
    cname varchar(32)

    );

    insert into course (cname) values('語文');
    insert into student (sname) values('數學');
    insert into student (sname) values('英語');
    insert into student (sname) values('化學');

    create table s_c(

    cid int,
    sid int

    );

    insert into s_c(sid, cid) values (1, 1);
    insert into s_c(sid, cid) values (1, 2);
    insert into s_c(sid, cid) values (1, 3);
    insert into s_c(sid, cid) values (1, 4);
    insert into s_c(sid, cid) values (2, 2);
    insert into s_c(sid, cid) values (2, 4);
    insert into s_c(sid, cid) values (3, 1);
    insert into s_c(sid, cid) values (3, 3);

2. 爲何要使用多張表

  • 避免出現大量的數據的冗餘
  • 並非表拆的越多越好,須要根據實際狀況進行拆分

3. 概念

  • 同時查詢多張表

4. 多表查詢的分類

<1> 合併查詢

  • union, union all
  • 合併結果集,就是把兩個select語句的查詢結果合併到一塊兒。(至關於並集)
  • 合併的兩個結果,列數和列的順序,類型須要一致

    create table emp(

    empno int primary key auto_increment,
    ename varchar(32)

    );

    create table dept(

    depeno int primary key auto_increment,
    dname varchar(32)

    );

    select from emp union select from dept;
    select from emp union all select from dept;

<2> 鏈接查詢

-- 員工表
create table emp(
    empno int primary key auto_increment,  # 員工編號
    ename varchar(32),  # 員工姓名
    job varchar(32),      # 員工職位
    mgr int,                          # 上級編號
    hiredate date,          # 入職時間
    sal double,                  # 薪資
    comm double,              # 獎金
    deptno int                  # 員工所屬部門
);

-- 部門表
create table dept(
    deptno int primary key auto_increment,  # 部門編號
    dname varchar(32),  # 部門名稱
    loc varchar(32)          # 部門地址
);
  • 內鏈接

    • inner join .... on 、 join , ,
    • inner join 是一個比較運算符,只返回符合條件的行
    • 例如:

      • select * from emp inner join dept on emp.deptno=dept.deptno;
      • select * from emp e, dept d where e.deptno = d.deptno;
      • select * from emp e join dept d where e.deptno = d.deptno;
  • 外鏈接

    • 左外鏈接 LEFT OUTER JOIN | left join .... on

      • 表明查詢,左邊行的所有,右邊沒有則null
      • select * from emp e LEFT OUTER JOIN dept d on e.deptno = d.deptno;
    • 右外鏈接 right join | right outer join .... on

      • 有鏈接包含right join 右表全部的行,若是左表中某行在右表沒有匹配,則結果中對應的左表的部分所有爲空(null)
      • select * from emp e RIGHT OUTER JOIN dept d on e.deptno = d.deptno;
  • 自鏈接

    • 自鏈接就是說,在同一個數據表中,看做是兩個表,表示查找每一個人的領導,若是沒有領導,則顯示無領導
    • 把一張表看做成兩張表,一張員工表,一張領導表,都是emp表
    • select e.ename, el.ename from emp e left join emp el on e.mgr = el.empno;
  • 天然鏈接: natural join (join) | natural left join (同 left join) | natural right join (同 right join)

    • 天然鏈接會自動判斷,以兩個表中相同的字段爲鏈接條件,返回查詢結果。
    • 注意: 內鏈接不寫鏈接條件會出現笛卡爾積的結果,應該避免這種狀況,而外鏈接不寫鏈接條件會報錯
    • select * from emp natural join dept;
    • select * from emp NATURAL left join dept;
    • select * from emp NATURAL right join dept;

<3> 子查詢 (ANY子查詢、IN子查詢、SOME子查詢、ALL子查詢)

  • 子查詢解決的問題:

    • 誰的薪資比張三高

      • select sal from emp where ename='張三'
  • 定義

    • 子查詢容許把一個查詢嵌套在另外一個查詢當中
    • 子查詢又叫作內部查詢,至關於內部查詢,包含內部查詢的就成爲外部查詢,子查詢的結果被主查詢所使用。
  • 注意的問題:

    • 括號
    • 能夠在主查詢的where select having from 後面,均可以使用子查詢
    • 不能夠在group by 後面使用子查詢
    • 主查詢和子查詢能夠不是同一張表;只有子查詢返回的值,主查詢能夠使用
      需求:查詢部門名稱是人力部的員工信息
      -- 第一種方式:利用子查詢
      select * from emp where deptno=(select deptno from dept where dname='人力部')
      -- 第二種方式:利用關聯查詢
      select * from emp e, dept d where e.deptno = d.deptno and d.dname = '人力部';

      SQL優化: 儘可能使用多表查詢

      絕大部分的子查詢在最終執行的時候都是轉換成一個多表查詢來執行的。 經過SQL的執行計劃能夠看出來
           經過SQL執行計劃會發現兩種方式執行的同樣的。
    • from 後面的子查詢
      需求:

      查詢員工號  姓名  薪資
      select empno, ename, sal from emp;
    • 通常不在子查詢中進行排序
    • 通常先執行子查詢,再去執行主查詢

ANY 關鍵字

假設any內部的查詢返回結果個數是三個,如: result1, result2, result3, 那麼
select .... from .... where a > any(....)
->
select .... from .... where a > result1 or a > result2 or a > result3

需求:
    查詢工資比1號部門中任意一個員工高的員工信息
    select * from emp where sal > any(select sal from emp where deptno = 1);

ALL 關鍵字

  • ALL 關鍵字與 ANY 關鍵字相似,只不過把上面的or 改爲 and

    select .... from .... where a > all(....)
    ->
    select .... from .... where a > result1 and a > result2 and a > result3

    需求:

    查詢工資比1號部門中全部員工高的員工信息

    select * from emp where sal > any(select sal from emp where deptno = 1);
    select * from emp where sal > all(select sal from emp where deptno = 1);

SOME 關鍵字

some 關鍵字和 any 關鍵字是同樣的功能,因此:
select .... from .... where a > any(....)
->
select .... from .... where a > result1 or a > result2 or a > result3

IN 關鍵字

In 運算符用於where 表達式中,以列表項的形式支持多個選擇,語法以下:
    where column in (v1, v2, v3 ....);
    where column not in (v1, v2, v3 ....);
    當in 前面加上not 運算符時,表示與in 相反的意思,即不在這些列表項中選擇。
    

案例:
    查詢部門名稱是人力部和研發部的員工
select * from emp where deptno in (select deptno from dept where dname = '人力部' or dname = '研發部');
相關文章
相關標籤/搜索