【數據庫】1.mysql相關知識(三)

4. 表連接

4.1 連接類型

  • INNER JOIN 內連接
  • LEFT JOIN 左外連接
  • RIGHT JOIN 右外連接
  • FULL OUTR JOIN 全連接這個在mysql中是沒有的
  • ON 連接條件

在這裏插入圖片描述

4.1.1 INNER JOIN 內連接

  • 什麼叫做內連接?看如下步驟
    • 假設有兩張表,數字爲id
        A表           B表
        1             2
        --------      --------
        2             3
        --------      --------
        3             4
        --------      --------
    
    • 然後篩選出id相同的數據,在這裏會做笛卡爾積運算,也就是行程一個新表
        新表
        A1 B2
        A1 B3
        A1 B4
        A2 B2
        A2 B3
        A2 B4
        A3 B2
        A3 B3
        A3 B4
    
    • 然後選出條件相同的結果,假設條件是id一樣
        最終結果表
        A2 B2
        A3 B3
    
  • 內連接SQL的寫法,有2種
    • 寫法一:
          SELECT * FROM student,score 
          WHERE student.id = score.student_id;
      
    • 寫法二:
          SELECT * FROM student INNER JOIN score
          ON student.id = score.student_id;
      
    • 注意:在這裏,如果只寫如下SQL,則會把所有結果都列出來,假設A表有5條記錄,B表有7條記錄,那麼結果就是5*7即35條記錄
        SELECT * FROM student,score;
        //或
        SELECT * FROM student INNER JOIN score;
    

4.1.2 LEFT JOIN 左外連接

  • 什麼叫做左外連接?看如下步驟
    • 複雜求解方法:
      • 假設有兩張表,數字爲id
          A表           B表
          1             2
          --------      --------
          2             3
          --------      --------
          3             4
          --------      --------
          5
          --------
      
      • 先補齊AB表的id,補到對齊,但id爲NULL
      A表           B表
      1             NULL(1)
      --------      --------
      2             2
      --------      --------
      3             3
      --------      --------
      NULL(4)       4
      --------      --------
      5             NULL(5)
      --------      --------
      
      • 然後做笛卡爾積,得到一個新表
      新表
      A1 NULL(B1)
      A1 B2
      A1 B3
      A1 B4
      A1 NULL(B5)
      
      A2 NULL(B1)
      A2 B2
      A2 B3
      A2 B4
      A2 NULL(B5)
      
      A3 NULL
      A3 B2
      A3 B3
      A3 B4
      A3 NULL(B5)
      
      NULL(A4) NULL(B1)
      NULL(A4) B2
      NULL(A4) B3
      NULL(A4) B4
      NULL(A4) NULL(B5)
      
      A5 NULL(B1)
      A5 B2
      A5 B3
      A5 B4
      A5 NULL(B5)
      
      • 然後先不管NULL,選出滿足條件的結果,假設條件爲id相等
      新表
      A1        NULL(B1)
      A2        B2
      A3        B3
      NULL(A4)  B4
      A5        NULL(B5)
      
      • 左外連接,以左邊爲標準,去掉左邊爲NULL的記錄,則爲結果(記得把右側NULL後面的括號去掉,因爲這是自己做個草稿的))
      A1        NULL
      A2        B2
      A3        B3
      A5        NULL
      
    • 更加簡便的方法:
      • 假設上面兩張表,找出id一樣的,左外連接
      • 先找出跟A表id一樣的記錄,然後將A表剩餘未找到一樣id的記錄拿出來,右側全部置爲NULL即可
          A表           B表
          1             2
          --------      --------
          2             3
          --------      --------
          3             4
          --------      --------
          5
          --------
      
          |
          |先找出id一樣的
          |
          ↓
          A2 B2
          A3 B3
          |
          |再找出左邊有的,右邊的全部值爲NULL
          |
          ↓
          A1 NULL
          A5 NULL
          |
          |兩張表拼起來即可
          |
          ↓
          A1 NULL
          A2 B2
          A3 B3
          A5 NULL
      
      
    • 左連接SQL語句寫法:
          SELECT * FROM student LEFT JOIN score ON student.id = score.student_id;
      

4.1.3 RIGHT JOIN 右連接

  • 思路與左連接一樣
  • 右連接SQL語句寫法:
    SELECT * FROM student RIGHT JOIN score ON student.id = score.student_id;

4.1.4 多表連接(利用內、左、右連接來處理多表數據)

  • 假設我需要得到學生姓名 課程 分數的表
    SELECT name,course_name,grade FROM student LEFT JOIN score ON student.id = score.student_id;

4.2 無限分類[自身連接]

  • 就是自己與自己這兩張一樣的表進行連接

4.2.1 建表

  • 表名:category
id name parent_id
1 數碼產品 0
2 服裝 0
3 食品 0
4 ipad 1
5 李寧 2
6 康師傅方便麪 3
7 橘子 3

4.2.2 查詢所有的頂級分類下面的類別的數量

  • 首先,分析是查詢自己表中的頂級分類和自己表中的其他類別的數量
  • 所以,屬於自身連接
  • 那麼,就先自己與自己內連接一番
    • 自己跟自己內連接,需要給兩個自己分別取別名
    SELECT * FROM category as c1 INNER JOIN category as c2;
  • 這樣,得到的是所有內連接的記錄。
  • 現在要從內連接的記錄中,篩選出c1的id是c2的parent_id的記錄
    SELECT * FROM category as c1 INNER JOIN category as c2 ON c1.id = c2.parent_id;
  • 得到的結果是:
id name parent_id id(1) name(1) parent_id(1)
1 數碼產品 0 4 ipad 1
2 服裝 0 5 李寧 2
3 食品 0 6 康師傅方便麪 3
  • 然後需要獲取頂級的類別下的,也就是c1.id=0
    SELECT * FROM category as c1 INNER JOIN category as c2 ON c1.id = c2.parent_id
    WHERE c1.id = 0;
  • 然後因爲需要篩選出對應頂級類別的數量,所以要對頂級類別分類
    SELECT * FROM category as c1 INNER JOIN category as c2 ON c1.id = c2.parent_id
    WHERE c1.parent_id = 0
    GROUP BY c1.id;    
  • 然後需要篩選出類別id,名字和數量
    SELECT c1.id,c1.name,COUNT(*) FROM category as c1 INNER JOIN category as c2 ON c1.id = c2.parent_id
    WHERE c1.parent_id = 0
    GROUP BY c1.id;    

4.2.3 把所有的父ID變成名稱,父ID爲0,則忽略

    SELECT c1.id,c1.name,c2.name AS 父類名稱 FROM category AS c1 INNER JOIN category AS c2 ON c1.parent_id = c2.id
id name 父類名稱
4 ipad 數碼產品
5 李寧 服裝
6 康師傅方便麪 食品
7 橘子 食品

4.3 刪除重複記錄(面試題,背下來,必須要會)

  • 總體思路:先篩選出需要刪除的ID,然後將這些ID的記錄刪除
    – 如何找出需要刪除的ID
    – 先根據名字分類,然後找出總數大於1的,說明是重複的
    – 原表 與 對總數大於1的表 左連接
        SELECT c1.id FROM category AS c1 LEFT JOIN (SELECT id,name FROM category GROUP BY name HAVING COUNT(*) > 1) AS c2 ON c1.name = c2.name
        WHERE c1.id != c2.id;
    

– 用IN、NOT IN也可以實現

```
    SELECT * FROM category AS c1 
    WHERE c1.name IN
    (SELECT name FROM category GROUP BY name HAVING COUNT(*) > 1)
    AND c1.id NOT IN
    (SELECT MIN(id) FROM category GROUP BY name HAVING COUNT(*) > 1)
```
  • 實現真正的刪除
    DELETE FROM category
    WHERE name IN
    (SELECT name FROM (SELECT name FROM category GROUP BY name HAVING COUNT(*) > 1) AS t1)
    AND id NOT IN
    (SELECT id FROM (SELECT MIN(id) AS id FROM category GROUP BY name HAVING COUNT(*) > 1) AS t2);

4.4 多表聯合更新

  • 所謂的多表聯合更新,其實就是,比如:
    • A表中的city列,抽出來一個city表,然後將A表中的city變成city表中的id。這樣不管city中的城市名稱怎麼變,都跟A表無關,因爲對應的是id,而id是不會變的。
    • 如果北京的id是3,你將city中的id改成了4,對不起,A表中對應北京的city_id依舊還是3,不會自動更新,因爲不是外鍵。

4.4.1 實現效果:修改山東省,所有的山東省都會修改掉

  • 如何實現:
    • 建立省份表,然後將省份關聯成省份表的id

    // 創建省份表
    CREATE TABLE province(
        id int PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(64)
    )

    // 填充省份表中的數據
    // 如何填充?
        // 學生表中的省份去重,然後插入到省份表

    INSERT INTO province(name) SELECT DISTINCT province FROM student;

    // 多表聯合更新: 更新省份,把student表中的province從漢字更新爲對應省份的id

    UPDATE student INNER JOIN province ON student.province = province.name
    SET student.province = province.id;

    // 一般來說,外鍵的名字爲當前列的名字加外檢表的列名,中間用下劃線鏈接,比如student表中province應該改成province_id,以及類型改爲int

    ALTER TABLE student CHANGE COLUMN province province_id INT NOT NULL AFTER city;


4.4.2 實戰操作:修改student中的city,所有對應的city都會變

    //創建city表
    CREATE TABLE city(
        id int PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(64) NOT NULL
    );

    // 填充city表的數據,從student中篩選出city,然後去重(取city的唯一值),插入到city表中
    INSERT INTO city(name) SELECT DISTINCT city FROM student;

    // 將student表中的city改爲對應city表中的id
    UPDATE student INNER JOIN  city ON student.city = city.name
    SET student.city = city.id;

    // 更新city列名稱爲city_id,類型爲int
    ALTER TABLE student CHANGE COLUMN city city_id INT NOT NULL AFTER age;

4.4.3 要掌握的語法

  • 將A表a字段插入到B表b字段
    • 關鍵字
      • DISTINCT 唯一的,不重複的
    INSERT TO B(b) SELECT DISTINCT a FROM A;
  • 更新表的數據
    UPDTE 表名 
    SET 字段=值;
  • 更新表某一列的設計,比如city列,名字改爲city_id,類型改爲int
    ALTER TABLE 表名 CHANGE COLUMN 老列名 新列名 [INT NOT NULL] AFTER 放在哪列後面的列名

    //舉例:
    // 更新city列名稱爲city_id,類型爲int
    ALTER TABLE student CHANGE COLUMN city city_id INT NOT NULL AFTER age;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章