4.2.2 去重 distinct
作用:去除SELECT查詢出來的結果中重復的數據,重復的數據只顯示一條
-- 查詢一下有哪些同學參加了考試
-- 查詢學生的全部考試信息,顯示result表的所有數據
SELECT * FROM `result`
-- 通過學號查詢哪些同學參加了考試,`StudentNo`表示學號
SELECT `StudentNo` FROM `result`
-- 去除重復的學號信息,重復的數據(此處指學號信息)只顯示一條
SELECT DISTINCT `StudentNo` FROM `result`
4.2.3 數據庫的列(表達式)
數據庫中的表達式:包括文本值、列、null、函數、計算表達式、系統變量等。
格式:SELECT 表達式 FROM 表
查看MySQL技術文檔:
5.7版本:MySQL :: MySQL 5.7 Reference Manual :: 12.1 Built-In Function and Operator Reference
https://dev.mysql.com/doc/refman/5.7/en/built-in-function-reference.html
8.0版本:MySQL :: MySQL 8.0 Reference Manual :: 12.1 Built-In Function and Operator Reference
https://dev.mysql.com/doc/refman/8.0/en/built-in-function-reference.html
-- 通過函數查看系統版本
SELECT VERSION(); -- 5.7.19
-- 用數學表達式來計算結果,將結果保存為“計算結果”
SELECT 100*3-1 AS '計算結果' -- 299
-- 查詢自增的步長(變量)
SELECT @@auto_increment_increment -- 1
-- 對數據進行某種整體運算,例:將學員考試成績+1后輸出
SELECT `StudentNo`,`StudentResult`+1 AS '提分后' FROM `result`
4.3 where條件字句
作用:檢索數據中符合條件的值,搜索的條件由一個或多個表達式組成,結果是布爾值。
常用的邏輯運算符:建議使用英文字母方式,見名知意!!!
運算符 | 語法 | 描述 |
---|---|---|
and 或 && | a and b 或 a&&b | 邏輯與,兩個都為真,結果為真 |
or 或 || | a or b 或 a||b | 邏輯或,其中一個為真,結果為真 |
not 或 ! | not a 或 !a | 邏輯非,非真則假,非假則真 |
-- 練習
-- 使用and查詢成績在95~100之間的學員
SELECT `StudentNo`,`StudentResult` FROM `result`
WHERE `StudentResult`>=95 AND `StudentResult`<=100
-- 使用&&查詢成績在95~100之間的學員
SELECT `StudentNo`,`StudentResult` FROM `result`
WHERE `StudentResult`>=95 AND `StudentResult`<=100
-- 使用or查看成績為60或95的學員
SELECT `StudentNo`,`StudentResult` FROM `result`
WHERE `StudentResult`=60 OR `StudentResult`=95
-- 使用||查看成績為60或95的學員
SELECT `StudentNo`,`StudentResult` FROM `result`
WHERE `StudentResult`=60 || `StudentResult`=95
-- 使用not查看學號不是10000的學員
SELECT `StudentNo`,`StudentResult` FROM `result`
WHERE NOT `StudentNo`=10000
-- 使用!查看學號不是10000的學員
SELECT `StudentNo`,`StudentResult` FROM `result`
WHERE `StudentNo`!=10000
-- 使用between... and...查看成績在90~100之間的學員
SELECT `StudentNo`,`StudentResult` FROM `result`
WHERE `StudentResult` BETWEEN 90 AND 100
-
模糊查詢:比較運算符
運算符 | 語法 | 描述 |
---|---|---|
IS NULL | a IS NULL | 如果操作符為NULL,結果為真 |
IS NOT NULL | a IS NOT NULL | 如果操作符不為NULL,結果為真 |
BETWEEN... AND ... | a BETWEEN b AND c | 如果a在b和c之間,結果為真 |
LIKE | a LIKE b | SQL匹配,如果a匹配b,結果為真 |
IN | a IN(a1,a2,a3,...) | 如果a為a1,a2...其中的某一個,結果為真 |
-
LIKE練習:模糊查詢
-- LIKE練習:%代表0~任意多個字符 _代表1個字符
-- 查詢姓李的同學:第一個字符為劉,后面的字符任意
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `StudentName` LIKE '李%'
-- 查詢姓李的同學:名字為兩個字的
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `StudentName` LIKE '李_'
-- 查詢姓李的同學:名字為三個字的
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `StudentName` LIKE '李__'
-- 查詢名字中帶有李字的同學,只要含有李字就行
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `StudentName` LIKE '%李%'
-
IN練習:精確查詢
-- IN:條件為具體的一個或多個值,並非模糊匹配,而是具體匹配
-- 查詢10000、10001、10002號學員
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `StudentNo` IN(10000,10001,10002)
-- 查詢在地址不詳的學員
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `Address` IN('地址不詳');
-- 查詢在地址不詳和北京市東城區的學員
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `Address` IN('地址不詳','北京市東城區');
-
NULL、NOT NULL練習:
-- 查詢地址為空的學生
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `Address`='' OR `Address` IS NULL
-- 查詢出生日期不為空的同學
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE `BornDate` IS NOT NULL
4.4 聯表查詢 join
我們在做查詢的時候,會遇到可能一張表滿足不了我們要求的情況,可能要求獲取的數據來自於兩張、三張甚至更多張表,對此,我們就應該使用聯表查詢。
-
3種JOIN對比:
-
實際JOIN理論細分可分為7種:
-- 練習:查詢參加了考試的同學,輸出學生信息:學號、姓名、科目編號、分數
-- 查詢所有學生信息
SELECT * FROM `student`
-- 查詢所有成績信息
SELECT * FROM `result`
/*
根據上面兩條語句查詢出來的效果,我們還需要一個一個對照着學生的學號去找,這種方式過於麻煩,因此我們需要用一種方式將這些數據拼接起來,方便我們查看。
思路:
1.分析需求:分析查詢的字段來自那些表?student、result
2.連接方式:確定使用哪種連接連接查詢?7種
確定交叉點:這兩個表中哪個數據是相同的
*/
-- join on 連接查詢(判斷的條件)
-- where 等值查詢
-- 分析兩張表結構,我們可以判斷的條件為:student表中的`StudentNo`=result表中的`StudentNo`
-- 1.使用INNER JOIN:內連接,也稱為自然連接
-- 注意: 內連接是從結果中刪除其他被連接表中沒有匹配行的所有行,所以內連接可能會丟失信息。
-- 重點:內連接,只查匹配行。
-- 語法:INNER可省略,單獨寫JOIN時,默認INNER JOIN
SELECT s.`StudentNo`,`StudentName`,`SubjectNo`,`StudentResult`
FROM `student` AS `s`
INNER JOIN `result` AS `r`
WHERE s.`StudentNo`=r.`StudentNo`
輸出結果:保留兩個表中都有匹配的行
-- 外連接:與內連接相比,即使沒有匹配行,也會返回一個表的全集。
-- 外連接分為三種:左外連接,右外連接,全外連接,對應SQL:LEFT/RIGHT/FULL OUTER JOIN。
-- 通常我們省略outer 這個關鍵字,寫成:LEFT/RIGHT/FULL JOIN。
-- 重點:至少有一方保留全集,沒有匹配行用NULL代替。
-- 1.LEFT OUTER JOIN,簡稱LEFT JOIN,左外連接(左連接)
-- 結果集保留左表的所有行,但只包含第二個表與第一表匹配的行,第二個表相應的空行被放入NULL值。
-- 通過結果,可以看到左連接包含了第一張表的所有信息,在第二張表中如果沒有匹配項,則用NULL代替
-- 2.RIGHT OUTER JOIN,簡稱RIGHT JOIN,右外連接(右連接)
-- 右外連接保留了第二個表的所有行,但只包含第一個表與第二個表匹配的行,第一個表相應空行被入NULL值。
-- 通過結果,可以看到右連接包含了第二張表的所有信息,在第一張表中如果沒有匹配項,則用NULL代替
-- 3.FULL OUTER JOIN,簡稱FULL JOIN,,全外連接(全連接)
-- 全外連接,簡稱:全連接,會把兩個表所有的行都顯示在結果表中
-- 包含了兩張表的所有記錄,沒有記錄丟失,沒有匹配的行用NULL代替。
--
-- 2.使用RIGHT JOIN 側重於result
SELECT * FROM `student`
SELECT * FROM `result`
SELECT s.`StudentNo`,`StudentName`,`SubjectNo`,`StudentResult`
FROM `student` AS `s`
RIGHT JOIN `result` AS `r`
ON s.`StudentNo`=r.`StudentNo` -- 此處使用ON
參考鏈接:
-
SQL的連表查詢 詳細s562872451的博客-CSDN博客連表查詢 https://blog.csdn.net/s562872451/article/details/80474726
-
SQL多表連接查詢(詳細實例) - 博雅源 - 博客園 https://www.cnblogs.com/wgphp/p/8183812.html
輸出結果:輸出右表的所有信息,左表中沒有匹配的行信息用NULL填充
-- 3.使用LEFT JOIN 側重於student
SELECT * FROM `student`
SELECT * FROM `result`
SELECT s.`StudentNo`,`StudentName`,`SubjectNo`,`StudentResult`
FROM `student` AS `s`
LEFT JOIN `result` AS `r`
ON s.`StudentNo`=r.`StudentNo` -- 此處使用ON
輸出結果:輸出左表的所有信息,右表中沒有匹配的行信息用NULL填充
JOIN ON 連接查詢 --- ON在連接查詢中均適用
WHERE 等值查詢 --- 在INNER JOIN可以使用
-
INNER JOIN、LEFT JOIN、RIGHT JOIN結果對比:
操作 | 描述 |
---|---|
INNER JOIN | 如果表中至少有一個匹配,就返回;如果兩張表都有,就確定是哪張表即可 |
LEFT JOIN | 會從左表中返回所有的值,即使右表中沒有匹配 |
RIGHT JOIN | 會從右表中返回所有的值,即使左表中沒有匹配 |
-- 查詢缺考的同學:側重於找出成績為NULL的同學,故使用LEFT JOIN
SELECT s.`StudentNo`,`StudentName`,`SubjectNo`,`StudentResult`
FROM `student` `s`
LEFT JOIN `result` `r`
ON s.`StudentNo`=r.`StudentNo`
WHERE `StudentResult` IS NULL
-- 思考題:查詢參加考試的同學信息:學號、學生姓名、科目名稱、分數
/*
思路:
1.分析需求,分析查詢的字段來自哪些表?student、result、subject
2.確定使用哪種連接查詢?7種
確定交叉點:這兩個表中哪個數據是相同的
判斷的條件:`student`表中的`StudentNo`=`result`表中的`StudentNo`
`result`表中的`SubjectNo`=`subject`表中的`SubjectNo`
*/
-- 先連接查詢student表、result表,用StudentNo進行連接
SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM `student` s
RIGHT JOIN `result` r -- 側重於參加考試同學的成績分數,故使用RIGHT JOIN
ON s.`StudentNo`=r.`StudentNo`
-- 再連接查詢result表、subject表,用SubjectNo進行連接
INNER JOIN `subject` sub
ON r.`SubjectNo`=sub.`SubjectNo`
-- 或
-- 先連接查詢student表、result表,用StudentNo進行連接
SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM `student` s
RIGHT JOIN `result` r -- 側重於參加考試同學的成績分數,故使用RIGHT JOIN
ON s.`StudentNo`=r.`StudentNo`
-- 再連接查詢result表、subject表,用SubjectNo進行連接
LEFT JOIN `subject` sub
ON r.`SubjectNo`=sub.`SubjectNo`
輸出結果:
總結:
-
我要查詢哪些數據? select...
-
從哪幾個表查? from 表 join方法 連接的表 on 交叉條件
-
假設存在一種多張表查詢,慢慢來,先查詢兩張表,然后再慢慢增加。
4.5 自連接查詢
定義:自己的表和自己的表連接,核心:一張表拆為兩張一樣的表即可。
在school數據庫中添加catalog表
-- 創建category表:categoryid為子類id,pid為父類id
DROP TABLE IF EXISTS `category`;
CREATE TABLE IF NOT EXISTS `category`(
`categoryid` INT(3) NOT NULL COMMENT '子類id',
`pid` INT(3) NOT NULL COMMENT '父類id,如果沒有父類id,則為1',
`categoryname` VARCHAR(10) NOT NULL COMMENT '種類名字',
PRIMARY KEY (`categoryid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
-- 插入category數據
INSERT INTO `category` (`categoryid`,`pid`,`categoryname`)
VALUES (2,1,'信息技術'),
(3,1,'軟件開發'),
(5,1,'美術設計'),
(4,3,'數據庫'),
(8,2,'辦公信息'),
(6,3,'web開發'),
(7,5,'ps技術');•
輸出結果:
我們分析這張表,可以看出,在這張表內實現了分級,例如:信息技術子類id=2,父類id=1,而數據庫子類id=4,父類id=1。我們可以根據上述規則將這張表拆分為兩個表:
-
父類:父類id都是1的
categoryid | categoryname | pid |
---|---|---|
2 | 信息技術 | 1 |
3 | 軟件開發 | 1 |
5 | 美術設計 | 1 |
-
子類:父類id不是1的,即上面剩下的數據
categoryid | categoryname | pid |
---|---|---|
4 | 數據庫 | 3 |
6 | web開發 | 3 |
7 | ps技術 | 5 |
8 | 辦公信息 | 2 |
操作:查詢父類對應的子類關系
父類 | 子類 |
---|---|
信息技術 | 辦公信息 |
軟件開發 | 數據庫 |
軟件開發 | web開發 |
美術設計 | ps技術 |
-- 對於都在一個表中的字段,我們就使用自連接查詢
-- 查詢父子信息:把一張表拆為兩個一模一樣的表
-- 拆名字
SELECT a.`categoryname` AS 父欄目 ,b.`categoryname` AS 子欄目
-- 拆表
FROM `category` AS a,`category` AS b
-- 通過id進行連接
WHERE a.`categoryid`=b.`pid` -- 此處不能調換位置,要一一對應
輸出結果:
-- 通過自連接查詢實現
SELECT a.`categoryname` 科目類別,b.`categoryname` 課程
FROM `category` a
INNER JOIN `category` b -- 此處只能用INNER JOIN
ON a.`categoryid`=b.`pid` -- 此處不能調換位置,要一一對應
輸出結果:
-- 補充練習:
-- 1.查詢學員所屬的年級,輸出學員的信息:學號、學生姓名、年級名稱
SELECT `StudentNo`,`StudentName`,`gradeName`
FROM `student` s
INNER JOIN `grade` g
ON s.`GradeID`=g.`gradeID`
-- 與上面結果相同,只是順序有交換
SELECT `StudentNo`,`StudentName`,`gradeName`
FROM `student` s
LEFT JOIN `grade` g
ON s.`GradeID`=g.`gradeID`
輸出結果:
-- 2.查詢科目所屬年級,輸出科目名稱、年級名稱
SELECT `SubjectName`,`gradeName`
FROM `subject` s
INNER JOIN `grade` g
ON s.`GradeID`=g.`gradeID`
-- 與上面結果相同,只是順序有交換
SELECT `SubjectName`,`gradeName`
FROM `subject` s
LEFT JOIN `grade` g
ON s.`GradeID`=g.`gradeID`
輸出結果:
-- 3.查詢參加數據庫結構-1考試的同學信息:學號、學生姓名、科目名稱、分數
SELECT s.`StudentNo`,`StudentName`,`SubjectName`,`StudentResult`
FROM `student` s
INNER JOIN `result` r
ON s.`StudentNo`=r.`StudentNo`
RIGHT JOIN `subject` sub -- 側重於所有科目
ON r.`SubjectNo`=sub.`SubjectNo`
WHERE `SubjectName`='數據庫結構-1' -- 單獨選出數據庫結構-1考試一科
輸出結果: