产品网站免费模板下载,域名空间申请,深圳营销型网站建设哪家好,邯郸哪里制作网站多表查询 文章目录 多表查询一、链表查询1.1交叉连接1.2 内连接1.3 左连接1.4 右连接1.5 全连接1.6 例子 二、子查询2.1 in与not in2.2 any/some2.3 all2.4 比较运算符2.5 exists 三、例子 查询中使用的表如下所示 ------------
| id | name |
------------
| 1 | IT |
…多表查询 文章目录 多表查询一、链表查询1.1交叉连接1.2 内连接1.3 左连接1.4 右连接1.5 全连接1.6 例子 二、子查询2.1 in与not in2.2 any/some2.3 all2.4 比较运算符2.5 exists 三、例子 查询中使用的表如下所示 ------------
| id | name |
------------
| 1 | IT |
| 2 | 销售 |
| 3 | 运营 |
| 4 | 安保 |
--------------------------------------
| id | name | age | dep_id |
--------------------------
| 1 | 张三 | 20 | 1 |
| 2 | 李四 | 25 | 3 |
| 3 | 王五 | 30 | 2 |
| 4 | 赵六 | 31 | 2 |
| 5 | 阿七 | 18 | NULL |
--------------------------一、链表查询
链表查询的本质是将多张表拼接在一块形成一张新表再对新表进行查询。 SELECT 字段 FROM 表1 INNER|LEFT|RIGHT JOIN 表2 ON 表1.字段 表2.字段;
1.1交叉连接
#交叉连接不能加任何的匹配条件生成的结果是两张表的笛卡尔积
select * from employee,department;
--------------------------------------
| id | name | age | dep_id | id | name |
--------------------------------------
| 1 | 张三 | 20 | 1 | 4 | 安保 |
| 1 | 张三 | 20 | 1 | 3 | 运营 |
| 1 | 张三 | 20 | 1 | 2 | 销售 |
| 1 | 张三 | 20 | 1 | 1 | IT |
| 2 | 李四 | 25 | 3 | 4 | 安保 |
| 2 | 李四 | 25 | 3 | 3 | 运营 |
| 2 | 李四 | 25 | 3 | 2 | 销售 |
| 2 | 李四 | 25 | 3 | 1 | IT |
| 3 | 王五 | 30 | 2 | 4 | 安保 |
| 3 | 王五 | 30 | 2 | 3 | 运营 |
| 3 | 王五 | 30 | 2 | 2 | 销售 |
| 3 | 王五 | 30 | 2 | 1 | IT |
| 4 | 赵六 | 31 | 2 | 4 | 安保 |
| 4 | 赵六 | 31 | 2 | 3 | 运营 |
| 4 | 赵六 | 31 | 2 | 2 | 销售 |
| 4 | 赵六 | 31 | 2 | 1 | IT |
| 5 | 阿七 | 18 | NULL | 4 | 安保 |
| 5 | 阿七 | 18 | NULL | 3 | 运营 |
| 5 | 阿七 | 18 | NULL | 2 | 销售 |
| 5 | 阿七 | 18 | NULL | 1 | IT |
--------------------------------------1.2 内连接
#内连接是根据匹配条件将两张表的公共部分连接起来
select * from employee inner join department on employee.dep_iddepartment.id;
--------------------------------------
| id | name | age | dep_id | id | name |
--------------------------------------
| 1 | 张三 | 20 | 1 | 1 | IT |
| 2 | 李四 | 25 | 3 | 3 | 运营 |
| 3 | 王五 | 30 | 2 | 2 | 销售 |
| 4 | 赵六 | 31 | 2 | 2 | 销售 |
--------------------------------------1.3 左连接
#左连接是以左表为基准将右表符合匹配条件的信息拼接到左表左表中匹配不上的记录会被保留
select * from employee left join department on employee.dep_iddepartment.id;
----------------------------------------
| id | name | age | dep_id | id | name |
----------------------------------------
| 1 | 张三 | 20 | 1 | 1 | IT |
| 2 | 李四 | 25 | 3 | 3 | 运营 |
| 3 | 王五 | 30 | 2 | 2 | 销售 |
| 4 | 赵六 | 31 | 2 | 2 | 销售 |
| 5 | 阿七 | 18 | NULL | NULL | NULL |
----------------------------------------1.4 右连接
#右连接是以右表为基准将左表符合匹配条件的信息拼接到右表右表中匹配不上的记录会被保留
select * from employee right join department on employee.dep_iddepartment.id;
----------------------------------------
| id | name | age | dep_id | id | name |
----------------------------------------
| 1 | 张三 | 20 | 1 | 1 | IT |
| 4 | 赵六 | 31 | 2 | 2 | 销售 |
| 3 | 王五 | 30 | 2 | 2 | 销售 |
| 2 | 李四 | 25 | 3 | 3 | 运营 |
| NULL | NULL | NULL | NULL | 4 | 安保 |
----------------------------------------1.5 全连接
#全连接是将两张表根据匹配条件拼接记录同时保留两张表中匹配不到的记录。
#由于mysql不支持full join操作所以使用union来模拟全连接操作
#union的作用是将两张表合并这个关键字会自动完成去重、排序等操作。
select * from employee left join department on employee.dep_iddepartment.id
union
select * from employee right join department on employee.dep_iddepartment.id;
------------------------------------------
| id | name | age | dep_id | id | name |
------------------------------------------
| 1 | 张三 | 20 | 1 | 1 | IT |
| 2 | 李四 | 25 | 3 | 3 | 运营 |
| 3 | 王五 | 30 | 2 | 2 | 销售 |
| 4 | 赵六 | 31 | 2 | 2 | 销售 |
| 5 | 阿七 | 18 | NULL | NULL | NULL |
| NULL | NULL | NULL | NULL | 4 | 安保 |
------------------------------------------1.6 例子
#现在需要针对上面的表格查询出销售部门的员工信息并按年龄升序排序
#在链表操作中如果字段只有某一张表含有可以直接写字段不用写为表.字段的形式
#如下方order by后的age只有employee有可以直接写age不用写为employee.age
select * from employee inner join department on employee.dep_iddepartment.id
where department.name销售 order by age;
--------------------------------------
| id | name | age | dep_id | id | name |
--------------------------------------
| 3 | 王五 | 30 | 2 | 2 | 销售 |
| 4 | 赵六 | 31 | 2 | 2 | 销售 |
--------------------------------------#查询IT部门的员工姓名、年龄信息
select employee.id,employee.name,age from employee inner join department
on employee.dep_iddepartment.id where department.nameIT;
------------------
| id | name | age |
------------------
| 1 | 张三 | 20 |
------------------二、子查询
子查询是指先查询一张表的信息将查询到的信息作为另一张表的查询条件继续查询以此重复直到查询出结果。
2.1 in与not in
#查询销售部门的员工信息
#下面的查询语句中先查询department表销售部门的id再查询dep_id与id一致的员工信息
#需要注意的是如果select后只有一个字段查询结果返回的是一个集合可以使用in如果select后是多个字段查询结果是一张表无法使用in
select * from employee where dep_id in (select id from department where name销售);
--------------------------
| id | name | age | dep_id |
--------------------------
| 3 | 王五 | 30 | 2 |
| 4 | 赵六 | 31 | 2 |
--------------------------#需要注意not in无法处理null
#例如寻找没有员工的部门由于括号中的查询结果返回集合含有nullnot in无法处理以此结果为空
select * from department where id not in (select dep_id from employee);
Empty set (0.00 sec)#对上述的问题可以这样改进
select * from department where id not in (select dep_id from employee where dep_id is not null);
------------
| id | name |
------------
| 4 | 安保 |
------------2.2 any/some
any表示某一个的意思它与in的区别是any后面必须是查询的结果不能直接是集合。 mysql中some的用法和any完全一致。 例如select * from t1 where id in (1,2);可以但是select * from t1 where idany (1,2);则不行。
#查询每个部门年龄最大的员工
#ageany和age in其实是等价的
#而any的意思是比集合中某一个大翻译一下就是比集合中最小的那个大就行同样的any的意思是比集合中某一个小翻译一下就是比集合中最大的那个小就行
select * from employee where age
any(select max(age) from employee where dep_id is not null group by dep_id);
--------------------------
| id | name | age | dep_id |
--------------------------
| 1 | 张三 | 20 | 1 |
| 2 | 李四 | 25 | 3 |
| 4 | 赵六 | 31 | 2 |
--------------------------
2.3 all
all表示所有的意思all和any一样后面不能直接加集合只能比较查询结果
#查询年龄比所有部门平均年龄高的员工信息
select * from employee where age
all(select avg(age) from employee where dep_id is not null group by dep_id);
--------------------------
| id | name | age | dep_id |
--------------------------
| 4 | 赵六 | 31 | 2 |
--------------------------#查询年龄比某一个部门平均年龄高的员工信息
select * from employee where age
any(select avg(age) from employee where dep_id is not null group by dep_id);
--------------------------
| id | name | age | dep_id |
--------------------------
| 2 | 李四 | 25 | 3 |
| 3 | 王五 | 30 | 2 |
| 4 | 赵六 | 31 | 2 |
--------------------------2.4 比较运算符
比较运算符有、!、、、、、
#查询年龄比所有员工平均年龄大的员工信息
select * from employee where age(select avg(age) from employee);
--------------------------
| id | name | age | dep_id |
--------------------------
| 2 | 李四 | 25 | 3 |
| 3 | 王五 | 30 | 2 |
| 4 | 赵六 | 31 | 2 |
--------------------------2.5 exists
exists关字键字表示存在。使用exists时内层查询语句不返回查询的记录而是返回一个真假值。当内存查询语句查询到记录时返回True外层查询语句返回结果反之则返回False外层查询语句不返回结果。
exists的执行过程
依次执外部查询然后为外部查询返回的每一行分别执行一次子查询子查询如果返回记录则exists条件成立外部查询语句返回结果
下面拿exists和in的执行进行比较in的子查询会先产生结果集然后外部查询再去结果集里去找符合要求的字段返回结果。由此可以看出exists的查询效率是远不如in的。
#由于department中没有id5的记录使用exists返回False以此外层的查询语句不执行
select * from employee where exists(select * from department where id5);
Empty set (0.00 sec)#查询有部门的员工的员工信息
select * from employee where
exists(select * from department where employee.dep_iddepartment.id);
--------------------------
| id | name | age | dep_id |
--------------------------
| 1 | 张三 | 20 | 1 |
| 2 | 李四 | 25 | 3 |
| 3 | 王五 | 30 | 2 |
| 4 | 赵六 | 31 | 2 |
--------------------------三、例子
使用到的表生成代码如下
/*数据导入Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version : 50624Source Host : localhostSource Database : sqlexamTarget Server Type : MySQLTarget Server Version : 50624File Encoding : utf-8Date: 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)
) ENGINEInnoDB AUTO_INCREMENT5 DEFAULT CHARSETutf8;-- ----------------------------
-- 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)
) ENGINEInnoDB AUTO_INCREMENT5 DEFAULT CHARSETutf8;-- ----------------------------
-- 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)
) ENGINEInnoDB AUTO_INCREMENT53 DEFAULT CHARSETutf8;-- ----------------------------
-- 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)
) ENGINEInnoDB AUTO_INCREMENT17 DEFAULT CHARSETutf8;-- ----------------------------
-- 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)
) ENGINEInnoDB AUTO_INCREMENT6 DEFAULT CHARSETutf8;-- ----------------------------
-- Records of teacher
-- ----------------------------
BEGIN;
INSERT INTO teacher VALUES (1, 张磊老师), (2, 李平老师), (3, 刘海燕老师), (4, 朱云海老师), (5, 李杰老师);
COMMIT;SET FOREIGN_KEY_CHECKS 1;例子中表的结构如下所示 现在需要针对表中的数据进行如下的操作
#查询物理课程比生物课程高的学生的学号
select b.student_id from
(select student_id,num as biology from score where course_id in
(select cid from course where cname生物)) as b
inner join
(select student_id,num as physcis from score where course_id in
(select cid from course where cname物理)) as p
on b.student_idp.student_id
where b.biologyp.physcis;
------------
| student_id |
------------
| 6 |
| 7 |
| 8 |
------------#查询挂科超过两门(包括两门)的学生姓名和班级
select sname,caption from class inner join student on cidsid where sid in
(select student_id from score where num60 group by student_id having count(num)2);
----------------------
| sname | caption |
----------------------
| 理解 | 三年二班 |
----------------------#查询所有选修了学号为1的同学选修过的一门或者多门课程的同学学号和姓名
select distinct sname,student.sid from student inner join score on student_idstudent.sid
where course_id in(select course_id from score where student_id1) and student_id!1;
-------------
| sname | sid |
-------------
| 钢蛋 | 2 |
| 张三 | 3 |
| 张一 | 4 |
| 张二 | 5 |
| 张四 | 6 |
| 铁锤 | 7 |
| 李三 | 8 |
| 李一 | 9 |
| 李二 | 10 |
| 李四 | 11 |
| 如花 | 12 |
-------------#查询在所有选修了李平老师课程的学生中这些课程(李平老师的课程不是所有课程)平均成绩最高的学生姓名
select sname,avg(num) from student inner join score on student.sidstudent_id where course_id
in((select cid from course inner join teacher on tidteacher_id where tname李平老师))
group by sname order by avg(num) desc limit 1;
------------------
| sname | avg(num) |
------------------
| 张四 | 100.0000 |
------------------#查询不同课程但成绩相同的学号课程号成绩
select s1.student_id,s1.course_id,s1.num,s2.student_id,s2.course_id,s2.num
from score as s1,score as s2
where s1.nums2.num and s1.course_id!s2.course_id;
--------------------------------------------------------
| student_id | course_id | num | student_id | course_id | num |
--------------------------------------------------------
| 8 | 1 | 9 | 1 | 2 | 9 |
| 7 | 1 | 9 | 1 | 2 | 9 |
| 6 | 1 | 9 | 1 | 2 | 9 |
| 3 | 2 | 66 | 1 | 4 | 66 |
| 12 | 2 | 77 | 3 | 1 | 77 |
| 11 | 2 | 77 | 3 | 1 | 77 |
| 10 | 2 | 77 | 3 | 1 | 77 |
| 1 | 4 | 66 | 3 | 2 | 66 |
| 12 | 4 | 87 | 3 | 3 | 87 |
| 11 | 4 | 87 | 3 | 3 | 87 |
| 10 | 4 | 87 | 3 | 3 | 87 |
| 8 | 2 | 100 | 4 | 4 | 100 |
| 7 | 2 | 100 | 4 | 4 | 100 |
| 6 | 2 | 100 | 4 | 4 | 100 |
| 8 | 2 | 100 | 5 | 4 | 100 |
| 7 | 2 | 100 | 5 | 4 | 100 |
| 6 | 2 | 100 | 5 | 4 | 100 |
| 1 | 2 | 9 | 6 | 1 | 9 |
| 6 | 4 | 100 | 6 | 2 | 100 |
| 5 | 4 | 100 | 6 | 2 | 100 |
| 4 | 4 | 100 | 6 | 2 | 100 |
| 8 | 2 | 100 | 6 | 4 | 100 |
| 7 | 2 | 100 | 6 | 4 | 100 |
| 6 | 2 | 100 | 6 | 4 | 100 |
| 1 | 2 | 9 | 7 | 1 | 9 |
| 6 | 4 | 100 | 7 | 2 | 100 |
| 5 | 4 | 100 | 7 | 2 | 100 |
| 4 | 4 | 100 | 7 | 2 | 100 |
| 9 | 2 | 88 | 7 | 4 | 88 |
| 1 | 2 | 9 | 8 | 1 | 9 |
| 6 | 4 | 100 | 8 | 2 | 100 |
| 5 | 4 | 100 | 8 | 2 | 100 |
| 4 | 4 | 100 | 8 | 2 | 100 |
| 9 | 2 | 88 | 8 | 4 | 88 |
| 8 | 4 | 88 | 9 | 2 | 88 |
| 7 | 4 | 88 | 9 | 2 | 88 |
| 3 | 1 | 77 | 10 | 2 | 77 |
| 13 | 3 | 87 | 10 | 4 | 87 |
| 3 | 3 | 87 | 10 | 4 | 87 |
| 3 | 1 | 77 | 11 | 2 | 77 |
| 13 | 3 | 87 | 11 | 4 | 87 |
| 3 | 3 | 87 | 11 | 4 | 87 |
| 3 | 1 | 77 | 12 | 2 | 77 |
| 13 | 3 | 87 | 12 | 4 | 87 |
| 3 | 3 | 87 | 12 | 4 | 87 |
| 12 | 4 | 87 | 13 | 3 | 87 |
| 11 | 4 | 87 | 13 | 3 | 87 |
| 10 | 4 | 87 | 13 | 3 | 87 |
--------------------------------------------------------