zoukankan      html  css  js  c++  java
  • 05 多表查询与子查询

    多表查询

    将两张表一起查询,得出笛卡尔积,通过on来增加链表的条件,达到你想要的效果。

    内链接

    select * from employee inner join department on employee.dep_id=department.id;
    

    左链接

     select * from employee left join department on employee.dep_id=department.id;
    

    右链接

    select * from employee right join department on employee.dep_id=department.id;
    

    全外连接

    SELECT
    	* 
    FROM
    	employee
    	LEFT JOIN department ON employee.dep_id = department.id 
    UNION
    SELECT
    	* 
    FROM
    	employee
    	RIGHT JOIN department ON employee.dep_id = department.id;
    

    子查询

    带in关键字的子查询

    #查询平均年龄在25岁以上的部门名
    select id,name from department
        where id in 
            (select dep_id from employee group by dep_id having avg(age) > 25);
    
    #查看技术部员工姓名
    select name from employee
        where dep_id in 
            (select id from department where name='技术');
    
    #查看不足1人的部门名(子查询得到的是有人的部门id)
    select name from department where id not in (select distinct dep_id from employee);
    
    not in 无法处理null的值,即子查询中如果存在null的值,not in将无法处理,如下
    
    mysql> select * from emp;
    +----+------------+--------+------+--------+
    | id | name | sex | age | dep_id |
    +----+------------+--------+------+--------+
    | 1 | egon | male | 18 | 200 |
    | 2 | alex | female | 48 | 201 |
    | 3 | wupeiqi | male | 38 | 201 |
    | 4 | yuanhao | female | 28 | 202 |
    | 5 | liwenzhou | male | 18 | 200 |
    | 6 | jingliyang | female | 18 | 204 |
    | 7 | xxx | male | 19 | NULL |
    +----+------------+--------+------+--------+
    7 rows in set (0.00 sec)
    
    mysql> select * from dep;
    +------+--------------+
    | id | name |
    +------+--------------+
    | 200 | 技术 |
    | 201 | 人力资源 |
    | 202 | 销售 |
    | 203 | 运营 |
    +------+--------------+
    4 rows in set (0.00 sec)
    
    # 子查询中存在null
    mysql> select * from dep where id not in (select distinct dep_id from emp);
    Empty set (0.00 sec)
    
    # 解决方案如下
    mysql> select * from dep where id not in (select distinct dep_id from emp where dep_id is not null);
    +------+--------+
    | id | name |
    +------+--------+
    | 203 | 运营 |
    +------+--------+
    1 row in set (0.00 sec)
    
    !!!注意not in
    

    带any关键字的子查询

    注意:括号里的必须时子查询语句。

    # =any等价与in
    # </>等价于not in
    
    # ANY 和 IN 运算符不同之处1
    ANY 必须和其他的比较运算符共同使用,而且ANY必须将比较运算符放在 ANY 关键字之前,所比较的值需要匹配子查询中的任意一个值,这也就是 ANY 在英文中所表示的意义
    
    例如:使用 IN 和使用 ANY运算符得到的结果是一致的
    select * from employee where salary = any (
    select max(salary) from employee group by depart_id);
    
    select * from employee where salary in (
    select max(salary) from employee group by depart_id);
    
    结论:也就是说“=ANY”等价于 IN 运算符,而“<>ANY”则等价于 NOT IN 运算符
    
    # ANY和 IN 运算符不同之处2
    ANY 运算符不能与固定的集合相匹配,比如下面的 SQL 语句是错误的
    
    SELECT
    *
    FROM
    T_Book
    WHERE
    FYearPublished < ANY (2001, 2003, 2005) 
    

    带all关键字的子查询

    注意:括号里的必须时子查询语句。

    # all同any类似,只不过all表示的是所有,any表示任一
    erase
    查询出那些薪资比所有部门的平均薪资都高的员工=》薪资在所有部门平均线以上的狗币资本家
    select * from employee where salary > all (
    select avg(salary) from employee group by depart_id);
    查询出那些薪资比所有部门的平均薪资都低的员工=》薪资在所有部门平均线以下的无产阶级劳苦大众
    select * from employee where salary < all (
    select avg(salary) from employee group by depart_id);
    
    查询出那些薪资比任意一个部门的平均薪资低的员工=》薪资在任一部门平均线以下的员工select * from employee where salary < any ( select avg(salary) from employee group by depart_id); 
    查询出那些薪资比任意一个部门的平均薪资高的员工=》薪资在任一部门平均线以上的员工
    select * from employee where salary > any (
    select avg(salary) from employee group by depart_id);
    

    带比较运算符的子查询

    #比较运算符:=、!=、>、>=、<、<=、<>
    #查询大于所有人平均年龄的员工名与年龄
    mysql> select name,age from emp where age > (select avg(age) from emp);
    +---------+------+
    | name | age |
    +---------+------+
    | alex | 48 |
    | wupeiqi | 38 |
    +---------+------+
    2 rows in set (0.00 sec)
    
    
    #查询大于部门内平均年龄的员工名、年龄
    select t1.name,t1.age from emp t1
    inner join 
    (select dep_id,avg(age) avg_age from emp group by dep_id) t2
    on t1.dep_id = t2.dep_id
    where t1.age > t2.avg_age;
    

    带exists关键字的子查询

    exists关键字表示存在,在使用exists关键字的时候,内层查询语句不返回查询的记录。而是返回一个真假值,True或是False,当返回是True时,查询,反之则不查询。

    #department表中存在dept_id=203,Ture
    mysql> select * from employee
        ->     where exists
        ->         (select id from department where id=200);
    +----+------------+--------+------+--------+
    | id | name       | sex    | age  | dep_id |
    +----+------------+--------+------+--------+
    |  1 | egon       | male   |   18 |    200 |
    |  2 | alex       | female |   48 |    201 |
    |  3 | wupeiqi    | male   |   38 |    201 |
    |  4 | yuanhao    | female |   28 |    202 |
    |  5 | liwenzhou  | male   |   18 |    200 |
    |  6 | jingliyang | female |   18 |    204 |
    +----+------------+--------+------+--------+
    
    #department表中存在dept_id=205,False
    mysql> select * from employee
        ->     where exists
        ->         (select id from department where id=204);
    Empty set (0.00 sec)
    

    练习题

    1、查询所有的课程的名称以及对应的任课老师姓名
    SELECT
    	cname,
    	tname 
    FROM
    	course
    	INNER JOIN teacher 
    WHERE
    	course.teacher_id = teacher.tid
    2、查询学生表中男女生各有多少人
    SELECT
    	gender,
    	COUNT( sid ) 
    FROM
    	student 
    GROUP BY
    	gender
    3、查询物理成绩等于100的学生的姓名
    SELECT
    	sname
    FROM
    	student
    	INNER JOIN score ON student.sid = score.student_id 
    	AND score.num = 100
    	INNER JOIN course ON course.cid = score.course_id 
    WHERE
    	cid =2
    4、查询平均成绩大于八十分的同学的姓名和平均成绩
    SELECT
    	student.sname,
    	t1.avg_num 
    FROM
    	student
    	INNER JOIN ( SELECT student_id, avg( num ) avg_num FROM score GROUP BY student_id HAVING avg_num > 80 ) AS t1 ON t1.student_id = student.sid;
    5、查询所有学生的学号,姓名,选课数,总成绩
    SELECT
    	student.sid,
    	t1.sname,
    	t1.选课数,
    	t1.总成绩 
    FROM
    	student
    	INNER JOIN (
    	SELECT
    		sname,
    		count(course_id) 选课数,
    		sum(num) 总成绩 
    	FROM
    		student
    		INNER JOIN score ON student.sid = score.student_id 
    	GROUP BY
    	sname 
    	) AS t1 ON student.sname = t1.sname;
    6、 查询姓李老师的个数
    select count(tname) 个数 from teacher where tname regexp "^李";
    7、 查询没有报李平老师课的学生姓名
    SELECT
    	* 
    FROM
    	student 
    WHERE
    	sid NOT IN ( SELECT sid FROM score INNER JOIN ( SELECT * FROM teacher INNER JOIN course ON tid = teacher_id ) AS t1 ON cid = 4 );
    8、 查询物理课程比生物课程高的学生的学号
    SELECT
    	t1.student_id 
    FROM
    	( SELECT * FROM score WHERE course_id = 1 ) AS t1
    	INNER JOIN ( SELECT * FROM score WHERE course_id = 2 ) AS t2 ON t1.student_id = t2.student_id 
    WHERE
    	t1.num < t2.num;
    9、 查询没有同时选修物理课程和体育课程的学生姓名
    SELECT
    	sname 
    FROM
    	student 
    WHERE
    	sid IN (
    	SELECT
    		t1.student_id 
    	FROM
    		( SELECT * FROM score WHERE course_id = 2 ) AS t1
    	INNER JOIN ( SELECT * FROM score WHERE course_id = 3 ) AS t2 ON t1.student_id = t2.student_id 
    	);
    10、查询挂科超过两门(包括两门)的学生姓名和班级
    select student_id from score where num < 60 group by student_id having count(course_id) >= 2;
    11 、查询选修了所有课程的学生姓名
    SELECT
    	sname,
    	caption 
    FROM
    	(
    	SELECT
    		* 
    	FROM
    		student
    		INNER JOIN ( SELECT student_id FROM score WHERE num < 60 GROUP BY student_id HAVING count( course_id ) >= 2 ) AS t1 ON student.sid = t1.student_id 
    	) AS t2
    	INNER JOIN class ON t2.class_id = class.cid;
    12、查询李平老师教的课程的所有成绩记录
     SELECT
    	student_id,
    	cname,
    	num 
    FROM
    	score
    	INNER JOIN ( SELECT * FROM course INNER JOIN teacher ON teacher.tid = course.teacher_id WHERE tid = 2 ) AS t1 ON score.course_id = t1.cid;
    13、查询全部学生都选修了的课程号和课程名
    SELECT
    	sname,
    	cname,
    	course_id 
    FROM
    	student
    	INNER JOIN ( SELECT cname, course_id, student_id FROM course INNER JOIN score ON course.cid = score.course_id ) AS t2 ON t2.student_id = student.sid;
    14、查询每门课程被选修的次数
    SELECT
    	cname,次数 
    FROM
    	course
    	INNER JOIN ( SELECT course_id, COUNT( course_id ) 次数 FROM score GROUP BY course_id ) AS t1 ON t1.course_id = course.cid
    15、查询只选修了一门课程的学生姓名和学号
    SELECT
    	sname,
    	sid 
    FROM
    	student
    	INNER JOIN ( SELECT student_id FROM score GROUP BY student_id HAVING COUNT( course_id )= 1 ) AS t1 ON student.sid = t1.student_id
    16、查询所有学生考出的成绩并按从高到低排序(成绩去重)
    SELECT DISTINCT
    	* 
    FROM
    	score 
    ORDER BY
    	num DESC
    17、查询平均成绩大于85的学生姓名和平均成绩
    SELECT
    	sname,
    	avg_num 
    FROM
    	student
    	INNER JOIN ( SELECT student_id, AVG( num ) avg_num FROM score GROUP BY student_id HAVING AVG( num ) > 85 ) AS t1 ON student.sid = t1.student_id
    18、查询生物成绩不及格的学生姓名和对应生物分数
    SELECT
    	sname,
    	num 
    FROM
    	student
    	INNER JOIN ( SELECT * FROM score WHERE course_id = 1 AND num < 60 ) AS t1 ON student.sid = t1.student_id
    19、查询在所有选修了李平老师课程的学生中,这些课程(李平老师的课程,不是所有课程)平均成绩最高的学生姓名
    SELECT
    	sname,
    	avg_num 
    FROM
    	student
    	INNER JOIN (
    	SELECT
    		student_id,
    		avg( num ) avg_num 
    	FROM
    		score
    		INNER JOIN ( SELECT * FROM course INNER JOIN teacher ON course.teacher_id = teacher.tid WHERE tid = 2 ) AS t1 ON score.course_id = t1.cid 
    	GROUP BY
    		student_id 
    	) AS t2 ON student.sid = t2.student_id 
    ORDER BY
    	avg_num DESC 
    	LIMIT 1;
    20、查询每门课程成绩最好的前两名学生姓名
    SELECT
        score.student_id,
        t3.course_id,
        t3.first_num,
        t3.second_num
    FROM
        score
    INNER JOIN (
        SELECT
            t1.course_id,
            t1.first_num,
            t2.second_num
        FROM
            (
                SELECT
                    course_id,
                    max(num) first_num
                FROM
                    score
                GROUP BY
                    course_id
            ) AS t1
        INNER JOIN (
            SELECT
                score.course_id,
                max(num) second_num
            FROM
                score
            INNER JOIN (
                SELECT
                    course_id,
                    max(num) first_num
                FROM
                    score
                GROUP BY
                    course_id
            ) AS t ON score.course_id = t.course_id
            WHERE
                score.num < t.first_num
            GROUP BY
                course_id
        ) AS t2 ON t1.course_id = t2.course_id
    ) AS t3 ON score.course_id = t3.course_id
    WHERE
        score.num >= t3.second_num
    AND score.num <= t3.first_num;
    
  • 相关阅读:
    ES6的Generator函数
    2017年要学习的三个CSS新特性
    移动端H5页面遇到的问题总结
    移动端布局解决方案+神器
    利用HTML5的devicemotion事件实现手机摇一摇抽奖,年会抽奖
    JavaScript 中 for 循环
    HTML DOM对象的属性和方法介绍(原生JS方法)
    初识JSON
    让你的WizFi250适应各种气候
    JAVA复习2 JAVA开发环境配置
  • 原文地址:https://www.cnblogs.com/zhaokunhao/p/14973786.html
Copyright © 2011-2022 走看看