目錄
1、笛卡爾積
2、聯合查詢
2.1、內連接
2.2、外連接
1、笛卡爾積
笛卡爾積:
笛卡爾積是讓兩個表通過排列組合的方式,得到的一個更大的表。笛卡爾積的列數,是這兩個表的列數相加,笛卡爾積的行數,是這兩個表的行數相乘
觀察發現,其中有一些數據,是無意義的數據,上圖中,當表1的id和表2的student_ID相等時,才是有意義的數據
笛卡爾積,是簡單無腦的排列組合,把所有可能的情況都窮舉了一遍,包含一些合法的數據也包含非法的無意義的數據。進行多表查詢的時候,就需要把有意義的數據篩選出來,無意義的數據過濾掉
2、聯合查詢
設計數據時把表進行拆分,為了消除表中的字段的依賴關系,比如部分函數依賴,傳遞依賴。這時會導致一條SQL查出來的數據,對于業務來說是不完整的,我們就可以使用聯合查詢把關系中的數據全部查出來,在一個數據行中顯示詳細信息
create table class(class_id bigint primary key auto_increment, name varchar(50)
);
create table student (id bigint primary key auto_increment,name varchar(50) not null,class_id bigint
);
insert into class (name) values ('1班'), ('2班'), ('3班');
insert into student (name, class_id) values('張三',1), ('李四',1), ('王五',2), ('趙六',3);
?
聯合查詢時MYSQL是如何執行的?
1. 取多張表的笛卡爾積
語法:
select * from 表名,表名;
兩張表取笛卡爾積之后,有些數據是無效數據
2. 通過連接條件過濾掉無效數據
兩個表之間是有主外鍵關系的,只需要判斷兩個表中主外鍵字段是否相等即可select * from student, class where student.class_id = class.class_id;
3. 能過指定列查詢,來精減結果集
查詢列表中通過?表名.列名?的方式指定要查詢字段select student.id, student.name, class.name from student, class
where student.class_id = class.class_id;
通過給表名起別名的方式來簡化SQL語句(建議使用這種方式)
總結:
聯合查詢也叫表連接查詢
1. 首先確定哪幾張表要參與查詢
2. 根據表與表之間的主外鍵關系,確定過濾條件
3. 精減查詢字段,得到想要的結果
2.1、內連接
上述聯合查詢的過程就是內連接
語法:
第一個是標準的內連接的寫法,其中 inner 可以省略
第二個就是上述聯合查詢的案例
上述的幾種寫法,選一個合適的就行,一般 where 這種用得更多
案例:?
DROP TABLE IF EXISTS `score`;
DROP TABLE IF EXISTS `student`;
DROP TABLE IF EXISTS `class`;
DROP TABLE IF EXISTS `course`;-- ----------------------------
-- Table structure for class
-- ----------------------------CREATE TABLE `class` (`class_id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,PRIMARY KEY (`class_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of class
-- ----------------------------
INSERT INTO `class` VALUES (1, '計算機系2019級1班');
INSERT INTO `class` VALUES (2, '中文系2019級3班');
INSERT INTO `class` VALUES (3, '自動化2019級5班');-- ----------------------------
-- Table structure for course
-- ----------------------------CREATE TABLE `course` (`course_id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,PRIMARY KEY (`course_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of course
-- ----------------------------
INSERT INTO `course` VALUES (1, 'Java');
INSERT INTO `course` VALUES (2, '中國傳統文化');
INSERT INTO `course` VALUES (3, '計算機原理');
INSERT INTO `course` VALUES (4, '語文');
INSERT INTO `course` VALUES (5, '高階數學');
INSERT INTO `course` VALUES (6, '英文');-- ----------------------------
-- Table structure for student
-- ----------------------------CREATE TABLE `student` (`student_id` bigint NOT NULL AUTO_INCREMENT,`sn` varchar(6) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`mail` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`class_id` bigint NULL DEFAULT NULL,PRIMARY KEY (`student_id`) USING BTREE,UNIQUE INDEX `sn`(`sn` ASC) USING BTREE,INDEX `class_id`(`class_id` ASC) USING BTREE,CONSTRAINT `student_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `class` (`class_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '09982', '黑旋風李逵', 'xuanfeng@qq.com', 1);
INSERT INTO `student` VALUES (2, '00835', '菩提老祖', NULL, 1);
INSERT INTO `student` VALUES (3, '00391', '白素貞', NULL, 1);
INSERT INTO `student` VALUES (4, '00031', '許仙', 'xuxian@qq.com', 1);
INSERT INTO `student` VALUES (5, '00054', '不想畢業', NULL, 1);
INSERT INTO `student` VALUES (6, '51234', '好好說話', 'say@qq.com', 2);
INSERT INTO `student` VALUES (7, '83223', 'tellme', NULL, 2);
INSERT INTO `student` VALUES (8, '09527', '老外學中文', 'foreigner@qq.com', 2);-- ----------------------------
-- Table structure for score
-- ----------------------------CREATE TABLE `score` (`score_id` bigint NOT NULL AUTO_INCREMENT,`student_id` bigint NULL DEFAULT NULL,`course_id` bigint NULL DEFAULT NULL,`score` decimal(5, 2) NULL DEFAULT NULL,PRIMARY KEY (`score_id`) USING BTREE,INDEX `student_id`(`student_id` ASC) USING BTREE,INDEX `course_id`(`course_id` ASC) USING BTREE,CONSTRAINT `score_ibfk_1` FOREIGN KEY (`student_id`) REFERENCES `student` (`student_id`) ON DELETE RESTRICT ON UPDATE RESTRICT,CONSTRAINT `score_ibfk_2` FOREIGN KEY (`course_id`) REFERENCES `course` (`course_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of score
-- ----------------------------
INSERT INTO `score` VALUES (1, 1, 1, 70.50);
INSERT INTO `score` VALUES (2, 1, 3, 98.50);
INSERT INTO `score` VALUES (3, 1, 5, 33.00);
INSERT INTO `score` VALUES (4, 1, 6, 98.00);
INSERT INTO `score` VALUES (5, 2, 1, 60.00);
INSERT INTO `score` VALUES (6, 2, 5, 59.50);
INSERT INTO `score` VALUES (7, 3, 1, 33.00);
INSERT INTO `score` VALUES (8, 3, 3, 68.00);
INSERT INTO `score` VALUES (9, 3, 5, 99.00);
INSERT INTO `score` VALUES (10, 4, 1, 67.00);
INSERT INTO `score` VALUES (11, 4, 3, 23.00);
INSERT INTO `score` VALUES (12, 4, 5, 56.00);
INSERT INTO `score` VALUES (13, 4, 6, 72.00);
INSERT INTO `score` VALUES (14, 5, 1, 81.00);
INSERT INTO `score` VALUES (15, 5, 5, 37.00);
INSERT INTO `score` VALUES (16, 6, 2, 56.00);
INSERT INTO `score` VALUES (17, 6, 4, 43.00);
INSERT INTO `score` VALUES (18, 6, 6, 79.00);
INSERT INTO `score` VALUES (19, 7, 2, 80.00);
INSERT INTO `score` VALUES (20, 7, 6, 92.00);
?
(1)查詢 “許仙” 同學的 成績
select student.name, score.score from student, score where
student.student_id = score.student_id and student.name = '許仙';
五個步驟:
1. 確定查詢中涉及到哪些表
2. 對目標表取笛卡爾積
3. 確定連接條件
4. 確定對整個結果集的過濾條件
5. 精減查詢字段
(2)查詢所有同學的總成績,及同學的個人信息
1. 確定要參與查詢的表是 學生表 和 成績表
總成績要用分組查詢 group by,搭配聚合函數 sum()
3. 確定兩張表之間關聯關系
student.student_id = score.student_id
4. 按學生的ld進行分組,并在查詢列表中,使用聚合函數sum(分數),計算總分
5. 在查詢列表中精減和確定要查詢的列
selectst.student_id,stu.name,sum(sc.score) as 總分 fromstudent st, score sc where st.student_id = sc.student_id group bysc.student_id
(3)查詢所有同學的每門課的成績,及同學的個人信息
1. 確定要參與查詢的表
學生表、成績表、課程表2.3. 取笛卡爾積、確定表與表之間的連接條件(可以通過表結果查看連接條件)
student.student_id = score.student_id
course.course_id = score.course_id
4.?確定查詢的過濾條件where
不需要
5.?精減查詢字段
使用 join on 的方式進行查詢:
2.2、外連接
外連接分為左外連接、右外連接和全外連接三種類型,MySQL不?持全外連接。
? 左外連接:返回左表的所有記錄和右表中匹配的記錄。如果右表中沒有匹配的記錄,則結果集中對應字段會顯示為NULL。
? 右外連接:與左外連接相反,返回右表的所有記錄和左表中匹配的記錄。如果左表中沒有匹配的記錄,則結果集中對應字段會顯示為NULL。
? 全外連接:結合了左外連接和右外連接的特點,返回左右表中的所有記錄。如果某?邊表中沒有匹配的記錄,則結果集中對應字段會顯示為NULL。
以下圖兩張表為例:
使用內連接時沒有4班的數據
使用右外連接,會以 join 右邊的表為基準,這個表中的數據會全部顯示出來。左邊的表沒有與之匹配的記錄全部用NULL去填充
在student表中插入一個class表中沒有的數據,使用左外連接
再用回之前的案例:
“?老外學中文” 在學生表中存在,在成績表中不存在
查詢哪位同學沒有考試成績
1. 在同學表中有記錄
2. 在分數表中沒有該同學對應的記錄select * from student st left join score sc on st.student_id = sc.student_id;
進一步篩選:
select * from student st left join score sc on st.student_id = sc.student_id where sc.score_id is null;