資料庫查詢語句DQL
阿新 • • 發佈:2021-01-17
表與表之間的關係
- 概念:表與表之間的關係,在理解上,一張表中的資料對應另外一張表中的資料關係,從每一行理解。
一對一關係
一對多關係
多對多關係
一、資料庫查詢語句DQL
/* Navicat MySQL Data Transfer Source Server : localhost Source Server Version : 80022 Source Host : 127.0.0.1:3306 Source Database : db_school Target Server Type : MYSQL Target Server Version : 80022 File Encoding : 65001 Date: 2020-12-23 14:47:16 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for course -- ---------------------------- DROP TABLE IF EXISTS `course`; CREATE TABLE `course` ( `c_id` varchar(20) NOT NULL, `c_name` varchar(20) NOT NULL DEFAULT '', `t_id` varchar(20) NOT NULL, PRIMARY KEY (`c_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of course -- ---------------------------- INSERT INTO `course` VALUES ('01', '語文', '02'); INSERT INTO `course` VALUES ('02', '數學', '01'); INSERT INTO `course` VALUES ('03', '英語', '03'); -- ---------------------------- -- Table structure for score -- ---------------------------- DROP TABLE IF EXISTS `score`; CREATE TABLE `score` ( `s_id` varchar(20) NOT NULL, `c_id` varchar(20) NOT NULL, `s_score` int DEFAULT NULL, PRIMARY KEY (`s_id`,`c_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of score -- ---------------------------- INSERT INTO `score` VALUES ('01', '01', '80'); INSERT INTO `score` VALUES ('01', '02', '90'); INSERT INTO `score` VALUES ('01', '03', '99'); INSERT INTO `score` VALUES ('02', '01', '70'); INSERT INTO `score` VALUES ('02', '02', '60'); INSERT INTO `score` VALUES ('02', '03', '80'); INSERT INTO `score` VALUES ('03', '01', '80'); INSERT INTO `score` VALUES ('03', '02', '80'); INSERT INTO `score` VALUES ('03', '03', '80'); INSERT INTO `score` VALUES ('04', '01', '50'); INSERT INTO `score` VALUES ('04', '02', '30'); INSERT INTO `score` VALUES ('04', '03', '20'); INSERT INTO `score` VALUES ('05', '01', '76'); INSERT INTO `score` VALUES ('05', '02', '87'); INSERT INTO `score` VALUES ('06', '01', '31'); INSERT INTO `score` VALUES ('06', '03', '34'); INSERT INTO `score` VALUES ('07', '02', '89'); INSERT INTO `score` VALUES ('07', '03', '98'); -- ---------------------------- -- Table structure for student -- ---------------------------- DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `s_id` varchar(20) NOT NULL, `s_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '', `s_birth` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '', `s_sex` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '', `age` int DEFAULT NULL, `height` int DEFAULT NULL, PRIMARY KEY (`s_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of student -- ---------------------------- INSERT INTO `student` VALUES ('01', '趙雷', '1990-01-01', '男', '23', '160'); INSERT INTO `student` VALUES ('02', '錢電', '1990-12-21', '女', '26', '165'); INSERT INTO `student` VALUES ('03', '孫風', '1990-05-20', '男', '20', '155'); INSERT INTO `student` VALUES ('04', '李雲', '1990-08-06', '保密', '19', '180'); INSERT INTO `student` VALUES ('05', '周梅', '1991-12-01', '女', '22', '175'); INSERT INTO `student` VALUES ('06', '吳蘭', '1992-03-01', '女', '18', '167'); INSERT INTO `student` VALUES ('07', '鄭竹', '1989-07-01', '男', '24', '158'); INSERT INTO `student` VALUES ('08', '王菊', '1990-01-20', '女', '25', '176'); INSERT INTO `student` VALUES ('09', '李雲龍', '1990-01-20', '男', '26', '163'); -- ---------------------------- -- Table structure for teacher -- ---------------------------- DROP TABLE IF EXISTS `teacher`; CREATE TABLE `teacher` ( `t_id` varchar(20) NOT NULL, `t_name` varchar(20) NOT NULL DEFAULT '', PRIMARY KEY (`t_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of teacher -- ---------------------------- INSERT INTO `teacher` VALUES ('01', '張三'); INSERT INTO `teacher` VALUES ('02', '李四'); INSERT INTO `teacher` VALUES ('03', '王五');
1.1簡單查詢語句
-
簡單查詢
-- 1、使用查詢語句,將一張表中所有的資料查詢出來 SELECT * FROM student;(不推薦使用,在開發裡面,禁止使用) -- 推薦在查詢的時候,用欄位名稱替換*,欄位名可以只寫部分 SELECT s_id,s_name,s_birth,s_sex,age FROM student;
-
條件查詢:需要使用到關鍵字WHERE
-- 1、根據id值查詢指定的學生資料,結果集只有一條 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE s_id = 1; -- 2、查詢性別為男的所有學生資料,結果集有多條 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE s_sex = "男"; -- 3、多條件查詢,多個條件一起查詢,會使用到邏輯運算子,比如:查詢小於20歲的所有男學生 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE s_sex = "男" AND age < 20; -- 4、多條件查詢,多個條件一起查詢,比如:查詢所有的男學生,或者年齡小於20的 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE s_sex = "男" OR age < 20; -- 5、如果使用or條件,一定要注意sql注入 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE s_sex = "男" OR 1 = 1; -- 6、查詢出性別不等於男,會將女學生或者保密的學生 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE s_sex <> "男"; -- 7、使用條件選定範圍內的資料,不如查詢出年齡在18到22歲之間的學生 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE age > 18 AND age < 22; -- 8、選擇一定範圍內的資料可以使用關鍵字between,兩端資料都包含 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE age between 18 AND 22;
-
模糊查詢,需要使用到關鍵字like,在實際開發中,為了提高資料庫的查詢效率,要儘量避免使用模糊查詢,
-- 如果要使用模糊查詢,需要使用到佔位符:_和% -- _表示單個佔位符 -- % 多個佔位符 -- 使用模糊查詢,將姓李的所有學生查詢出來 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE s_name LIKE "李_"; -- 使用模糊查詢,查詢出名字中有李的名稱 SELECT s_id,s_name,s_birth,s_sex,age FROM student WHERE s_name LIKE "李%";
-
排序查詢:有一些欄位,可以通過對其進行排序查詢結果,排序分為升序和降序,要用到關鍵字ORDER BY
-- 排序語法:SELECT 欄位 FROM 表 ORDER BY 要排序的欄位 排序規則(ASC升序,DESC降序,預設升序) -- 按照學生的年齡進行升序排列 SELECT s_id,s_name,s_birth,s_sex,age FROM student ORDER BY age ASC; -- 按照學生的身高,降序排列 SELECT s_id,s_name,s_birth,s_sex,age,height FROM student ORDER BY height DESC;
-
分組查詢,在一個表中,按照特定的欄位進行分組,要使用到關鍵字GROUP BY
-- 5.7以後處理group by問題,在my.ini檔案中,新增上配置引數: [msyqld] sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' -- 查詢成績表,根據學號分組 SELECT s_id,c_id,s_score FROM score GROUP BY s_id; -- 在分組查詢中,要使用聚合函式,分組才有意義,聚合函式都是放在SELECT關鍵字後面 -- 1、查詢出一個分組中某一個欄位的和:SUM(欄位名) -- 2、查詢出一個分組中某一個欄位的平均數:AVG(欄位名) -- 3、統計出某一個分組的資料個數:COUNT(欄位名) -- 4、查詢出一個分組中某一個欄位的最大值:MAX(欄位名) -- 5、查詢出一個分組中某個欄位的最小值:MIN(欄位名) -- 查詢出每個學生的總成績 SELECT s_id,SUM(s_score) FROM score GROUP BY s_id; -- 查詢出每個學生的平均成績 SELECT s_id AS 學號,AVG(s_score) FROM score GROUP BY s_id; -- 統計出每個學生學了多少門課程 SELECT s_id AS 學號,COUNT(c_id) AS 課程數 FROM score GROUP BY s_id; -- 通過sum函式和count函式計算平均成績 SELECT s_id AS 學號,SUM(s_score) / COUNT(c_id) AS 平均成績 FROM score GROUP BY s_id; -- 找出該學生的最高成績 SELECT s_id AS 學號,MAX(s_score) FROM score GROUP BY s_id; -- 找出該學生的最低成績 SELECT s_id AS 學號,MIN(s_score) FROM score GROUP BY s_id; -- 找出平均成績高於60分的學生,如果是把聚合函式的結果作為條件再次篩選,則需要用關鍵字HAVING,並且放在GROUP BY後面 SELECT s_id AS 學號,AVG(s_score) AS 平均成績 FROM score GROUP BY s_id HAVING AVG(s_score) > 60; -- 將聚合函式的結果作為排序的條件 SELECT s_id AS 學號,SUM(s_score) AS 總成績 FROM score GROUP BY s_id ORDER BY SUM(s_score) DESC;
-
篩選個數,需要使用關鍵字LIMIT,在分頁的時候會使用到
-- 從查詢的結果集中,只要其中的幾條資料, -- 語法:LIMIT 起始位置(從0開始計數),查詢的條數; SELECT s_id,s_name,s_birth,s_sex,age,height FROM student LIMIT 0,5;
-
去重:會使用關鍵字DISTINCT,作用是將查詢結果集中的某些欄位的重複資料只保留一個
-- 查詢成績表,根據學號進行去重。比如:查詢出那些學生是有成績的 SELECT DISTINCT s_id FROM score;
1.2 查詢語句的執行順序
-
一條完整的查詢語句
SELECT DISTINCT 欄位 FROM 表名 WHERE 欄位條件 GROUP BY 欄位 HAVING 聚合函式條件 ORDER BY 欄位 排序規則 LIMIT 起始位置,顯示條數;
- 執行FROM,將硬碟中的資料放到記憶體中
- 執行WHERE,將普通欄位的條件進行篩選
- 查詢語句中是否有GROUP BY,如果有按照規則分組,如果沒有,則預設分為一個組
- 查詢語句中,是否有HAVING,如果有將聚合函式作為條件,進行篩選
- 執行SELECT,將要查詢的結果的欄位挑選出來
- 執行DISTINCT將結果中重複的資料只顯示一個
- 執行ORDER BY,如果沒有,則按照升序排列
- 篩選LIMIT
1.3 子查詢
-
可以實現多表查詢,將一個表查詢的結果,作為另外一張表的條件,進行查詢
-- 第一步:查詢出總成績最高的學生學號 SELECT s_id AS 學號 FROM socre GROUP BY s_id ORDER BY SUM(S_SCORE) DESC LIMIT 0,1; -- 第二步:查詢出01學號學生的所有資訊 SELECT s_id,s_name,s_birth,s_sex,age,height FROM student WHERE s_id = '01'; -- 如果已知條件就是兩張表,要求查詢出總成績最高的學生的資訊 SELECT s_id,s_name,s_birth,s_sex,age,height FROM student WHERE s_id = (SELECT s_id FROM score GROUP BY s_id ORDER BY SUM(s_score) DESC LIMIT 0,1); -- 查詢出有成績的學生的資訊 SELECT s_id,s_name,s_birth,s_sex,age,height FROM student WHERE s_id in (SELECT DISTINCT s_id FROM score); -- 查詢出沒有成績的學生資訊 SELECT s_id,s_name,s_birth,s_sex,age,height FROM student WHERE s_id not in (SELECT DISTINCT s_id FROM score); -- 查詢出平均成績高於60分的學生資訊 SELECT s_id,s_name,s_birth,s_sex,age,height FROM student WHERE s_id IN (SELECT s_id FROM score GROUP BY s_id HAVING AVG(s_score) > 60); -- exists:子查詢語句中有結果,則主查詢語句執行,如果子查詢語句中沒有結果,則主查詢語句不執行。 -- 舉例: SELECT s_id,s_name,s_sex,s_birth,age,height FROM student WHERE EXISTS(SELECT s_id FROM score WHERE s_score = 100);
1.4 連結查詢
-
一些複雜的查詢語句,在一張表中並不能查詢出結果,多表一起查詢,使用連結查詢將有關係的表進行連線,連結成一張表,然後在用篩選、分組、排序等進行操作。
-- 交叉連結:因為會產生笛卡爾積,因此禁止使用 -- 舉例:查詢所有學生的資訊及學生對應的成績 SELECT s1.s_id,s_name,s_sex,s_birth,age,height,s2.s_id,c_id,s_score FROM student AS s1,score AS s2 WHERE s1.s_id = s2.s_id; -- 內連線:......FROM 表1 INNER JOIN 表2 ON 主外來鍵連結條件 -- 舉例:查詢所有學生的資訊及學生對應的成績 SELECT s1.s_id,s_name,s_sex,s_birth,age,height,s2.s_id,c_id,s_score FROM student AS s1 INNER JOIN score AS s2 ON s1.s_id = s2.s_id; -- 內連線舉例:查詢出所有學生學習的課程資訊及對應的成績 SELECT s1.s_id,s_name,s_sex,s_birth,age,height,s2.s_id,s2.c_id,s_score,c.c_id,c_name,t_id FROM student AS s1 JOIN score AS s2 ON s1.s_id = s2.s_id JOIN course AS c ON s2.c_id = c.c_id; -- 在上面的基礎上, 可以繼續進行篩選,查詢出所有學生中成績最高的學生資訊、課程資訊和成績 SELECT s1.s_id,s_name,s_sex,s_birth,age,height,s2.s_id,s2.c_id,s_score,c.c_id,c_name,t_id FROM student AS s1 JOIN score AS s2 ON s1.s_id = s2.s_id JOIN course AS c ON s2.c_id = c.c_id ORDER BY s_score DESC LIMIT 0,1; -- 查詢出所有老師教的所有課程的所有成績的所有學生資訊 SELECT s1.s_id,s_name,s_sex,s_birth,age,height,s2.s_id,s2.c_id,s_score,c.c_id,c_name,c.t_id,t.t_id,t_name FROM student AS s1 JOIN score AS s2 ON s1.s_id = s2.s_id JOIN course AS c ON s2.c_id = c.c_id JOIN teacher AS t ON c.t_id = t.t_id; -- 外連線:左外連線和右外連線 -- 左外連線:以左邊的表為基準,右邊的表如果對應的沒有資料,則用null來表示,左邊的表一定要有資料,語法:FROM 表1 LEFT JOIN 表2 ON 條件。 SELECT s1.s_id,s_name,s_sex,s_birth,age,height,s2.s_id,c_id,s_score FROM student AS s1 LEFT JOIN score AS s2 ON s1.s_id = s2.s_id; -- 右外連線 -- 以右邊的表為基準,左邊的表如果對應的沒有資料,則用null來表示,右邊的表一定要有資料,語法:FROM 表1 RIGHT JOIN 表2 ON 條件。 SELECT s1.s_id,s_name,s_sex,s_birth,age,height,s2.s_id,c_id,s_score FROM student AS s1 RIGHT JOIN score AS s2 ON s1.s_id = s2.s_id;
tudent AS s1 LEFT JOIN score AS s2 ON s1.s_id = s2.s_id;
– 右外連線
– 以右邊的表為基準,左邊的表如果對應的沒有資料,則用null來表示,右邊的表一定要有資料,語法:FROM 表1 RIGHT JOIN 表2 ON 條件。
SELECT s1.s_id,s_name,s_sex,s_birth,age,height,s2.s_id,c_id,s_score FROM student AS s1 RIGHT JOIN score AS s2 ON s1.s_id = s2.s_id;