Mysql入門第四課《數據查詢》

原文在我的 Github 中,歡迎訂閱。

前言

前幾篇文章

之所以把數據查詢單拉一個文章,是因爲查詢牽扯的知識點比較多,可以說在增刪改查裏,查的複雜度也是最高的。

之前已經瞭解一點像WHERE id=2 這種非常簡單的條件語句。

單表查詢非常簡單,但開發中更多的是多表查詢,那我們以多表查詢來說道說道。

熱熱身

我們在處理數據時通過某個字段來查另一個跟它有關的信息,除了在數據庫中經常這樣操作,在前端也有類似情況。

先看一段前端經常遇到的數據:

{
    province:'江蘇省',
    citys:[
        '南京市',
        '蘇州市',
        '無錫市'
    ]
}

上面是把省市都揉到一起了,只嵌套了兩層,但如果嵌套個四五層,就像這樣:

{
   province:'江蘇省',
   children:[
    {
        name:'城市1',
        children:[
            name:'江寧區',
            children:[
                name:'XX小區'
            ]
        ]
    },
    {
        name:'城市2',
        children:[
            name:'AA區',
            children:[
                name:'BB小區'
            ]
        ]
    }
   ]
}

這種數據解析起來會瘋。

我們一直說數據扁平化,來 我們扁平一把:

// 省
const provice = [
    {
        province:'江蘇省',
        province_id: 1001
    },
    {
        province:'浙江省',
        province_id: 1002
    },
    ...
]

// 市
const citys = [
    {
      name:'南京市',
      province_id: 1001
    },
    {
      name:'蘇州市',
      province_id: 1001
    },
    
    {
      name:'杭州市',
      province_id: 1002
    },
    {
      name:'嘉興市',
      province_id: 1002
    },
    ...
]

//找到江蘇省下所有的城市
const result = citys.filter(i => i.province_id === 1001);

數據扁平化的好處就是,當不需要找城市的時候,citys 數據跟我無關,只需關心 province 就可以了,而且在查找性能上更快(有時候能免了遞歸)。

上面的例子引出下面這句話:在數據庫中,通過某些字段將表與表關聯起來,這就是關係型數據庫的核心。

準備幾張表

在圖中可以看到 student 表裏有 class_id,這樣 學生班級 通過 class_id就有了關聯,在開發中,我們可以通過它來查找class信息。

查詢

我們通過上面幾個表來查詢幾個需求:

  1. 查詢成績大於 60 分的學生,顯示學生的姓名和成績
  2. 查詢姓的老師的個數
  3. 查詢沒有學過馬上來老師課的學生姓名
  4. 查詢所有學生的姓名、選課數量、成績總和

我們一個一個來並分析。

查詢成績大於 60 分的學生,顯示學生的姓名和成績

SELECT t1.student_name, t2.number FROM 
student t1 LEFT JOIN score t2 ON t1.id=t2.student_id 
WHERE t2.number>60;

先看結果:

得到了正確數據。

分析語句:
t1t2分別是 student 和 score 的別名。
細心的同學能看出,我把上面的 sql 語句用三行來顯示,這是有寓意的喲:

  1. 第一行:要查詢的字段,這個非常好理解
  2. 第二行:其實它的結果是個臨時表!即對應查詢語句裏的 table_name !
  3. 第三行:通俗易通的WHERE條件語句

也就是說,它依然是符合通用語法:

SELECT column_name,column_name
FROM table_name
[WHERE Clause]
[LIMIT N][ OFFSET M]

只不過第二行生成了一個臨時表。

這裏牽扯到了 JOIN ON 語法,我會在後面的章節中專門細說,這裏推薦幾篇相關文章:

天空未藍](https://zhuanlan.zhihu.com/p/...

查詢姓馬的老師的個數

SELECT COUNT(id) AS teacher_num FROM teacher WHERE teacher_name LIKE '馬%';

解析:

  • COUNT(fieldName): COUNT 函數用於統計某字段數量
  • AS: 取別名
  • LIKE:一般與%使用,模糊搜索,如果不用%相當於精確搜索。
  • %:表示任意字符,類似於正則表達式裏的*

查詢所有學生的姓名、選課數量、成績總和

這個查詢比較複雜,我們先上 sql :

SELECT 
t1.student_name, 
IFNULL(t2.course_num,0) AS course_num, 
IFNULL(t2.sum_number,0) AS sum_number FROM 
student t1 
LEFT JOIN 
(SELECT student_id,count(id) course_num, SUM(number) AS sum_number FROM score GROUP BY student_id) t2 
ON t1.id=t2.student_id;

再看下結果:

先!不!要!慌! 我們一點一點來解析。

現在你腦海裏應該先浮現出通用查詢語句:

SELECT column_name,column_name
FROM table_name
[WHERE Clause]
[LIMIT N][ OFFSET M]

而圖中的查詢語句翻譯過來就是:

SELECT 學生名, 選課數量, 成績總和 FROM 表;

然後我們來拆分上圖中的查詢:
先看 SELECT student_id,count(id) course_num, SUM(number) AS sum_number FROM score GROUP BY student_id,我們單獨來執行這句看看結果:

這條語句爲我們生成了一個表,它顯示了 學生id、選課數、總成績,所以這張表示核心,但需求是讓我們展示所有的學生,所以我們必須依賴student查。

如果把上圖中查出來的結果 命名爲t2,就會變成:

SELECT 
t1.student_name, IFNULL(t2.course_num,0) AS course_num, IFNULL(t2.sum_number,0) AS sum_number 
FROM student t1 LEFT JOIN t2 
ON t1.id=t2.student_id;

再去掉些“多餘”的部分:

SELECT 
t1.student_name, t2.course_num, t2.sum_number 
FROM student t1 LEFT JOIN t2 
ON t1.id=t2.student_id;

哈哈,是不是一下就看懂了呢?

這裏再介紹下語句裏沒見過的東東:

  1. IFNULL(a,b):類似常見的 if 語句,判斷 a 是否爲 null,如果是則顯示 b。
  2. COUNT():對讀取的數據中的某字段計算出個數,一般用於查詢出數據的條數。
  3. SUM():求和,對讀取數據中的某個字段求和。
  4. GROUP BY:通過 GROUP BY 可以設定通過哪些字段對讀取的數據進行分組排序(默認升序),需要注意的是,GROUP BY 有分組聚合功能。

關於GROUP BY有幾篇文章可以看看:

附建表語句

下面是幾個表的建表語句:

-- 班級表
CREATE TABLE class(
    id INT UNSIGNED PRIMARY KEY auto_increment,
    caption VARCHAR(30) COMMENT '班級名'
);

-- 學生表
CREATE TABLE student(
    id INT UNSIGNED PRIMARY KEY auto_increment,
    student_name CHAR(30) COMMENT '學生名',
    gender CHAR(30) DEFAULT NULL    COMMENT '學生性別',
    class_id INT DEFAULT NULL COMMENT '班級id'
);

-- 老師表
CREATE TABLE teacher(
    id INT UNSIGNED PRIMARY KEY auto_increment,
    teacher_name CHAR(30) COMMENT '教師名'
);

-- 課程表
CREATE TABLE course(
 id INT UNSIGNED PRIMARY KEY auto_increment,
 course_name CHAR(30) COMMENT '課程名',
 teacher_id INT DEFAULT NULL COMMENT'教師id'
);

-- 成績表
CREATE TABLE score(
    id INT UNSIGNED PRIMARY KEY auto_increment,
    number INT DEFAULT NULL COMMENT '分數',
    student_id INT DEFAULT NULL COMMENT '學生id',
    course_id INT DEFAULT NULL COMMENT '課程id'
);

總結

這篇文章主要了解查詢,然而這也只是一個練習而已,實際開發中比這難的查詢有很多,需要自己平常沒事多練習。

今天工作比價忙,文章寫的可能有點糙,如果有哪裏不正確的地方歡迎指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章