1. 程式人生 > 資料庫 >資料庫查詢語句DQL

資料庫查詢語句DQL

表與表之間的關係

  • 概念:表與表之間的關係,在理解上,一張表中的資料對應另外一張表中的資料關係,從每一行理解。

一對一關係

image-20201223094835942

一對多關係

image-20201223095356024

多對多關係

image-20201223100621580

一、資料庫查詢語句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 起始位置,顯示條數;
    
  1. 執行FROM,將硬碟中的資料放到記憶體中
  2. 執行WHERE,將普通欄位的條件進行篩選
  3. 查詢語句中是否有GROUP BY,如果有按照規則分組,如果沒有,則預設分為一個組
  4. 查詢語句中,是否有HAVING,如果有將聚合函式作為條件,進行篩選
  5. 執行SELECT,將要查詢的結果的欄位挑選出來
  6. 執行DISTINCT將結果中重複的資料只顯示一個
  7. 執行ORDER BY,如果沒有,則按照升序排列
  8. 篩選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;