首页 > 数据库 >MySQL数据库——多表查询

MySQL数据库——多表查询

时间:2022-11-28 19:55:57浏览次数:36  
标签:多表 -- 数据库 teacher course student MySQL id SELECT

MySQL数据库——多表查询

一、多表查询的两种方式

1.1连表操作

'''
inner join	内连接
只连接两张表中公有的数据部分
'''
select * from emp inner join dep on emp.dep_id=dep.id;
'''
left join	左连接
以左表为基准,展示左表所有的数据,如果没有对应的项用NULL填充
'''
select * from emp left join dep on emp.dep_id=dep.id;
'''
right join	右连接
以右表为基准,展示右表所有的数据,如果没有对应项则用NULL填充
'''
select * from emp right join dep on emp.dep.id=dep.id;
'''
union	全连接
以左右为基准,展示所有的数据,各自没有的都以NULL填充
'''
select * from emp left join dep on emp.dep_id=dep.id
union
select * from emp right join dep on emp.dep_id=dep.id;
'''
学会了链表操作之后也就可以连接N多张表
	思路:
		将拼接之后的表起别名,当成一张表再去和其他表拼接,再起别名,再去和其他的表拼接,依次循环往复即可
'''

1.2子查询

'''
将一条SQL语句用()括起来,当成另外一条SQL语句的查询的条件
要求:
	求姓名是jason的员工所在的部门名称
思想:
	分步操作
'''
# 步骤1:现根据jason获取部门编号
select dep_id from emp where name='jason';
# 步骤2:再根据部门编号获取部门名称
select name from dep where id=(select dep_id from emp where name='jason');
'''
总结:
	很多时候多表查询需要结合实际情况判断用那种,更多的时候是互相配合使用
'''

二、多表查询练习

2.1 sql内容

/*
 数据导入:
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50624
 Source Host           : localhost
 Source Database       : sqlexam

 Target Server Type    : MySQL
 Target Server Version : 50624
 File Encoding         : utf-8

 Date: 10/21/2016 06:46:46 AM
*/

SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `class`
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `caption` varchar(32) NOT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `class`
-- ----------------------------
BEGIN;
INSERT INTO `class` VALUES ('1', '三年二班'), ('2', '三年三班'), ('3', '一年二班'), ('4', '二年九班');
COMMIT;

-- ----------------------------
--  Table structure for `course`
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `cname` varchar(32) NOT NULL,
  `teacher_id` int(11) NOT NULL,
  PRIMARY KEY (`cid`),
  KEY `fk_course_teacher` (`teacher_id`),
  CONSTRAINT `fk_course_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `course`
-- ----------------------------
BEGIN;
INSERT INTO `course` VALUES ('1', '生物', '1'), ('2', '物理', '2'), ('3', '体育', '3'), ('4', '美术', '2');
COMMIT;

-- ----------------------------
--  Table structure for `score`
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `student_id` int(11) NOT NULL,
  `course_id` int(11) NOT NULL,
  `num` int(11) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_score_student` (`student_id`),
  KEY `fk_score_course` (`course_id`),
  CONSTRAINT `fk_score_course` FOREIGN KEY (`course_id`) REFERENCES `course` (`cid`),
  CONSTRAINT `fk_score_student` FOREIGN KEY (`student_id`) REFERENCES `student` (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `score`
-- ----------------------------
BEGIN;
INSERT INTO `score` VALUES ('1', '1', '1', '10'), ('2', '1', '2', '9'), ('5', '1', '4', '66'), ('6', '2', '1', '8'), ('8', '2', '3', '68'), ('9', '2', '4', '99'), ('10', '3', '1', '77'), ('11', '3', '2', '66'), ('12', '3', '3', '87'), ('13', '3', '4', '99'), ('14', '4', '1', '79'), ('15', '4', '2', '11'), ('16', '4', '3', '67'), ('17', '4', '4', '100'), ('18', '5', '1', '79'), ('19', '5', '2', '11'), ('20', '5', '3', '67'), ('21', '5', '4', '100'), ('22', '6', '1', '9'), ('23', '6', '2', '100'), ('24', '6', '3', '67'), ('25', '6', '4', '100'), ('26', '7', '1', '9'), ('27', '7', '2', '100'), ('28', '7', '3', '67'), ('29', '7', '4', '88'), ('30', '8', '1', '9'), ('31', '8', '2', '100'), ('32', '8', '3', '67'), ('33', '8', '4', '88'), ('34', '9', '1', '91'), ('35', '9', '2', '88'), ('36', '9', '3', '67'), ('37', '9', '4', '22'), ('38', '10', '1', '90'), ('39', '10', '2', '77'), ('40', '10', '3', '43'), ('41', '10', '4', '87'), ('42', '11', '1', '90'), ('43', '11', '2', '77'), ('44', '11', '3', '43'), ('45', '11', '4', '87'), ('46', '12', '1', '90'), ('47', '12', '2', '77'), ('48', '12', '3', '43'), ('49', '12', '4', '87'), ('52', '13', '3', '87');
COMMIT;

-- ----------------------------
--  Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `gender` char(1) NOT NULL,
  `class_id` int(11) NOT NULL,
  `sname` varchar(32) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_class` (`class_id`),
  CONSTRAINT `fk_class` FOREIGN KEY (`class_id`) REFERENCES `class` (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `student`
-- ----------------------------
BEGIN;
INSERT INTO `student` VALUES ('1', '男', '1', '理解'), ('2', '女', '1', '钢蛋'), ('3', '男', '1', '张三'), ('4', '男', '1', '张一'), ('5', '女', '1', '张二'), ('6', '男', '1', '张四'), ('7', '女', '2', '铁锤'), ('8', '男', '2', '李三'), ('9', '男', '2', '李一'), ('10', '女', '2', '李二'), ('11', '男', '2', '李四'), ('12', '女', '3', '如花'), ('13', '男', '3', '刘三'), ('14', '男', '3', '刘一'), ('15', '女', '3', '刘二'), ('16', '男', '3', '刘四');
COMMIT;

-- ----------------------------
--  Table structure for `teacher`
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `tid` int(11) NOT NULL AUTO_INCREMENT,
  `tname` varchar(32) NOT NULL,
  PRIMARY KEY (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `teacher`
-- ----------------------------
BEGIN;
INSERT INTO `teacher` VALUES ('1', '张磊老师'), ('2', '李平老师'), ('3', '刘海燕老师'), ('4', '朱云海老师'), ('5', '李杰老师');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

2.2练习内容

'''
1、查询所有的课程的名称以及对应的任课老师姓名
2、查询平均成绩大于八十分的同学的姓名和平均成绩
3、查询没有报李平老师课的学生姓名
4、查询没有同时选修物理课程和体育课程的学生姓名
5、查询挂科超过两门(包括两门)的学生姓名和班级
'''
# 1、查询所有的课程的名称以及对应的任课老师姓名
# 1.1 先确定需要用的几张表(课程表、老师表)
# 1.2 预览表中数据、做到心中有数
SELECT * FROM course;
SELECT * FROM teacher;
# 1.3 确定多表查询的思路、连表、子查询、混合操作
SELECT
	teacher.tname,
	course.cname 
FROM
	course
	INNER JOIN teacher ON course.teacher_id = teacher.tid
# 2、查询平均成绩大于八十分的同学的姓名和平均成绩
# 2.1 先确定需要用的几张表(学生表、分数表)
# 2.2 预览表中数据
SELECT * FROM student;
SELECT * FROM score;
# 2.3 根据已知条件,先求出每个同学的平均成绩
SELECT
	student_id,
	AVG( num ) 
FROM
	score 
GROUP BY
	student_id 
HAVING
	AVG( num )> 80;
# 2.4 确定最终的结果需要几张表(学生表、分数表)多表查询
SELECT
	student.sname,
	student_score.avg_num 
FROM
	student
	INNER JOIN ( SELECT student_id, AVG( num ) AS avg_num FROM score GROUP BY student_id HAVING avg_num > 80 ) AS student_score ON student.sid = student_score.student_id;
# 3、查询没有报李平老师课的学生姓名
# 3.1 先确定需要用到几张表(老师表、课程表、学生表)
# 3.2 预览每张表的数据
SELECT * FROM teacher;
SELECT * FROM course;
SELECT * FROM student;
'''
3.3 确定思路:
	1:正向筛选
	2:筛选所有报了李平老师课程学生的id,然后取反
'''
# 获取李平老师教授的课程id
SELECT
	tid 
FROM
	teacher 
WHERE
	tname = '李平老师';

SELECT
	cid 
FROM
	course 
WHERE
	teacher_id = ( SELECT tid FROM teacher WHERE tname = '李平老师' );
# 根据课程id筛选出所有报了李平老师的学生id (distinct 去重)
SELECT DISTINCT student_id FROM score WHERE score.course_id IN (
SELECT
	cid 
FROM
	course 
WHERE
	teacher_id = ( SELECT tid FROM teacher WHERE tname = '李平老师' ));
# 根据学生id在学生表中取反获取学生姓名
SELECT
	sname 
FROM
	student 
WHERE
	sid NOT IN (
	SELECT DISTINCT
		student_id 
	FROM
		score 
	WHERE
		course_id IN (
		SELECT
			cid 
		FROM
			course 
	WHERE
	teacher_id = ( SELECT tid FROM teacher WHERE tname = '李平老师' )));
# 4、查询没有同时选修物理课程和体育课程的学生姓名
# 4.1 先确定需要的表(学生表、课程表)
# 4.2 预览表数据
SELECT * FROM student;
SELECT * FROM course;
# 4.3 筛选出物理和体育的cid 
SELECT cid FROM course WHERE cname IN ('物理','体育')
# 4.4 根据cid筛选出学生id
SELECT
	student_id 
FROM
	score 
WHERE
	course_id IN (
	SELECT
		cid 
	FROM
		course 
WHERE
	cname IN ( '物理', '体育' ))
# 4.4统计每个学生报的课程数,筛选出等于2的
SELECT
	student_id 
FROM
	score 
WHERE
	course_id IN (
	SELECT
		cid 
	FROM
		course 
WHERE
	cname IN ( '物理', '体育' ))
	GROUP BY student_id
	HAVING COUNT(course_id) = 2;
# 4.5 子查询获取学生姓名
SELECT
	sname 
FROM
	student 
WHERE
	sid IN (
	SELECT
		student_id 
	FROM
		score 
	WHERE
		course_id IN (
		SELECT
			cid 
		FROM
			course 
		WHERE
		cname IN ( '物理', '体育' )) 
	GROUP BY
		student_id 
	HAVING
	COUNT( course_id ) = 2 
	);
# 5、查询挂科超过两门(包括两门)的学生姓名和班级
# 5.1 先确定涉及到的表(学生表、班级表、分数表)
# 5.2 预览表数据
SELECT * FROM student;
SELECT * FROM score;
SELECT * FROM class;
# 5.3 筛选分数小于60的数据
SELECT num FROM score WHERE num<60;
# 5.4 统计每个学生小于60的次数
SELECT
	student_id,
	COUNT( course_id ) 
FROM
	score 
WHERE
	num < 60 
GROUP BY
	student_id;
# 5.5 筛选次数大于等于2的学生id
SELECT
	student_id,
	COUNT( course_id ) 
FROM
	score 
WHERE
	num < 60 
	GROUP BY student_id 
	HAVING COUNT( course_id ) >= 2;
# 5.6 连接班级与学生表,基于学生id筛选
SELECT
	student.sname,
	class.caption 
FROM
	student
	INNER JOIN class ON student.class_id = class.cid 
WHERE
	student.sid IN (SELECT student_id FROM score WHERE num < 60 GROUP BY student_id HAVING COUNT( course_id ) >= 2 );

三、小知识点补充

3.1 concat与concat_ws

'''
concat用于分组之前的字段拼接操作
'''
select concat(name,'|',sex) from emp;
'''
concat_ws用于拼接多个字段并且中间的连接符一致
'''
select concat_wa('|',name,sex,age) from emp;

3.2 exists

'''
判断是否存在
	sql2有结果的情况下才会执行sql1,否则不会执行sql1,返回空数据
	语法

SELECT column1 FROM t1 WHERE [conditions] and EXISTS (SELECT * FROM t2 );
说明

    括号中的子查询并不会返回具体的查询到的数据,只是会返回true或者false,如果外层sql的字段在子查询中存在则返回true,不存在则返回false
    即使子查询的查询结果是null,只要是对应的字段是存在的,子查询中则返回true,下面有具体的例子
'''
sql1 exists sql2;

3.3 表相关的SQL补充

# 重命名表名
alter table 表名 rename 新表名;
# 添加字段
alter table 表名 add 字段名 字段类型(长度) 约束条件;
# 修改字段
alter table 表名 add 字段名 字段类型(长度) 约束条件 after 已有字段;
alter table 表名 add 字段名 字段类型(长度) 约束条件 first;
# 删除字段
alter table 表名 change 旧字段名 新字段名 字段类型(长度) 约束条件;
alter table 表名 drop 字段名;

标签:多表,--,数据库,teacher,course,student,MySQL,id,SELECT
From: https://www.cnblogs.com/HaiMan/p/16933422.html

相关文章

  • 多表查询的两种方法、小知识点补充说明、可视化软件Navicat、多表查询练习题、python
    目录多表查询的两种方法小知识点补充说明可视化软件Navicat多表查询练习题python操作MySQLpymysql补充说明多表查询的两种方法两张表方式1:连表操作 innerjoin 内......
  • 多表查询的方法与第三方模块pymysql
    多表查询的两种方法方式一:连表操作内连接:关键字:innerjoinselect*fromempinnerjoindeponemp.dep_id=dep.id;只连接两张表中公有的数据部分左连接:......
  • MySQL日志管理、备份与恢复
    一.MySQL日志管理MySQL的日志默认保存位置为/usr/local/mysql/dataMySQL的日志配置文件为/etc/my.cnf ,里面有个[mysqld]项修改配置文件:vim/etc/my.cnf[mysqld]1......
  • python第三方模块之pymysql
    python第三方模块之pymysql首先我们要先向解释器中安装pymysql模块:pippymysql--install与数据库建立连接conn=pymysql.connect(host='127.0.0.1',#与本地......
  • 可视化软件Navicat与pymysql模块
    第三方开发的用来充当数据库客户端的简单快捷的操作界面 无论第三方软件有多么的华丽呼哨,底层的本质还是SQL能够操作数据库的第三方可视化软件有很多,其中针对MySQL最出门......
  • mysql多表查询
    今日内容概要多表查询的两种方法小知识点补充说明可视化软件Navicat多表查询练习题python操作MySQL今日内容详细方式1:连表操作 innerjoin 内连接 selec......
  • MySQL事务和存储引擎
    一、MySQL事务概述1.1、MySQL事务简介MySQL事务是访问并更新数据库中各种数据项的一个程序执行单元。在事务中的操作,要么都执行修改,要么都不执行,这就是事务的目的,也是事......
  • MySQL中的索引
    一、索引的概念索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址(类似于C语言的链表通过指针指向数据记录的内存地址)。使用索引后可......
  • 多表查询两种方法、可视化软件navicat、python操作mysql、pymysql模块
    目录多表查询的思路多表查询的两种方法小知识点补充数说明可视化软件Navicat多表查询练习题python操作MySQLpymysql补充说明多表查询的思路表数据准备表数据准备creat......
  • skywalking启动配置agent及数据储存对数据源(mysql,es)版本要求
    skywalking启动配置agent及数据储存对数据源(mysql,es)版本要求#skywalking-agent.jar的本地磁盘路径-javaagent:D:\SkyWalking\skywalking-agent\skywalking-agent.jar#......