1. 程式人生 > >MySQL數據庫基礎(筆記整理四)

MySQL數據庫基礎(筆記整理四)

情況 rom mys 生成 block 別名 表操作 嵌套 循環

多表查詢

當你打算從多個數據表選取信息時,有一種方法叫做聯結(join)。把一個數據表與另一個數據表中的信息結合起來才能得到查詢結果。聯結操作是通過並把兩個(或多個)數據表裏的同類數據進行匹配而完成的。多表操作的另一種方法是將SELECT語句嵌套在另一個SELECT語句裏,前者叫做子查詢。例如:

mysql>    SELECT student.name,grade_event.date, score.score, grade_event.category 
        ->    FROM grade_event INNER JOIN score INNER JOIN student 
        ->    ON grade_event.event_id = score.event_id 
        ->    AND score.student_id = student.student_id
        ->    WHERE grade_event.date = ‘2018-10-07‘ ;

這條查詢先查出給定日期的grade_event行,再利用此行裏的event_id 把score數據表裏擁有同一event_id 的考試分數都查出來,並且把score和student數據表裏都有student_id的數據列查出來,利用這個關系把學號映射為他們的姓名。每找到一組彼此都匹配的grade_event行和score行,score行和student行,就把學生的姓名、考試分數、日期和考試事件的類型顯示出來。這條查詢與單表查詢相比:

  • 在FROM子句裏,我們列舉出了多個數據表的名字,因為我們要從多個數據表裏檢索數據
  • 在ON子句裏,我們給出了grade_event數據表和score數據表,score數據表和student數據表的聯結條件,這grade_event和score數據表裏的event_id 列的值必須相互匹配(並且 為了消除歧義,這裏對event_id進行了完全限定),而score和student數據表裏的student_id列的值必須相互匹配。

換一種情況,加入現在有一個表是記錄學生們的考試缺考情況(absence表),如果你想看到缺考的學生信息,就需要把absence表與student表通過student_id 列的值聯結起來。例如:

mysql>    SELECT student.student_id, student.name,
        ->    COUNT(absence.date) AS absences
        ->    FROM student INNER JOIN absence 
        ->    ON student.student_id = absence.student_id
        ->    GROUP BY student.student_id;

上面的這條查詢對於想知道都有哪些學生缺考的情況,查詢結果正是我們需要的。但假如你需要對所有學生的考生出勤情況做一個統計,(即需要同時顯示出沒有缺考的學生信息)那麽我們就需要用LEFT JOIN來代替普通的聯結操作。 LEFT JOIN 將使MySQL 為聯結操作中第一個數據表(即關鍵字LEFT JOIN左邊的數據表)裏的每一個中選數據行生成一個輸出行。上例可以修改為:

mysql>    SELECT student.student_id, student.name,
        ->    COUNT(absence.date) AS absences
        ->    FROM student LEFT JOIN absence
        ->    ON student.student_id = absence.student_id 
        ->    GROUP BY student.student_id;

上面這條查詢,不僅可以列出缺考的學生的信息,還會返回沒有缺考的學生的信息,並且缺考次數統計為0 。

   RIGHT OUTER JOIN ....ON 即為右聯結,與左聯結正好相反,用法相同。其實對左聯結來說,將表的順序交換就是右聯結。還有全聯結(全外聯結),但MySQL不支持此種聯結方式。

聯結操作並非只能作用於不同的數據表,你可以把某個數據表和它自身結合起來。例如:你想知道在student表中是否有兩個同學籍貫相同。

mysql>    SELECT s1.name, s1.city, s1.state FROM student AS s1 INNER JOIN student AS s2 
        ->    ON s1.city = s2.city AND s1.state =s2.state 
        ->    WHERE (s1.name != s2.name)
        ->    ORDER BY state, city , name;

這條查詢有兩個需要註意的地方:

  • 它需要兩次用到同一個表,所以我們必須為它創建兩個別名(s1 和s2)才能把表中的同名數據列區分開來。
  • 用WHERE子句來確保每名學生的記錄只能與其他學生相匹配,來剔除“記錄與它本身相匹配”的情況。
   MySQL認為任何一個查詢都是一次“關聯” ,並不僅僅是一個查詢需要兩個表匹配才叫關聯,所以在MySQL中,每一個查詢,每一個片段(包括子查詢,甚至是基於單表查 詢)都可以是一次關聯。MySQL執行關聯的策略很簡單:MySQL對任何關聯都執行嵌套循環關聯操作。即MySQL先在一個表中循環取出單條數據,然後在嵌套循環到下一個表中尋找匹配的行,依次下去,直到找到所有表中的匹配行為止。然後根據各個表匹配的行,返回查詢需要的各個列。

多表檢索的另一類方法,嵌套查詢

嵌套查詢也就是它一條SELECT語句嵌套在另一條裏。例如:

mysql>    SELECT * FROM student WHERE student_id
        ->    NOT IN(SELECT student_id FROM absence);

上面的這條查詢把全體沒有缺勤的學生找出來。嵌套與內層的SELECT語句用來生成一個absence數據表裏出現過的student_id 值的集合,外層的SELECT語句負責把與該機合理的任何一個ID值都不匹配的student數據行檢索出來(NOT IN)。


2018/10/14 MySQL數據庫基礎筆記整理(四)

MySQL數據庫基礎(筆記整理四)