Javaweb笔记(九):多表查询小试牛刀(1)

上一文章对单表的查询进行了相关的练习。这一篇则尝试进行多表的查询,这个尝试中涉及到两张表,分别是emp表,dept 表,(emp表是员工信息表,dept是部门信息表)

员工信息表

071201.png

部门信息表

071202.png

针对上边两张表进行多表查询信息的操作:

1. 查出至少有一个员工的部门。显示部门编号、部门名称、部门位置、部门人数。

首先进行分析我们需要展示的列,和需要涉及到的表:
列:部门编号,部门名称,部门位置 -> 表dept 可以查询;部门人数->表emp分组查询
表:dept ,emp

select deptno , count(*) cnt from emp group by deptno;//对emp进行分组,查询每组的人数

mysql> select deptno , count(*) cnt from emp group by deptno
    -> ;
+--------+-----+
| deptno | cnt |
+--------+-----+
|     20 |   5 |
|     30 |   6 |
|     10 |   3 |
|     50 |   1 |
+--------+-----+
4 rows in set (0.00 sec)

select * from dept ;d //查询dept表的所有信息

mysql> select * from dept
    -> ;
+--------+-----------+--------+
| deptno | dname     | loc    |
+--------+-----------+--------+
|     10 | 教研部    | 北京   |
|     20 | 学工部    | 上海   |
|     30 | 销售部    | 广州   |
|     40 | 财务部    | 武汉   |
+--------+-----------+--------+
4 rows in set (0.00 sec)

两张表进行查询结果

select d.* ,z.cnt from dept d , (select deptno , count(*) cnt from emp group by deptno) z ;

mysql> select d.* ,z.cnt from dept d , (select deptno , count(*) cnt from emp group by deptno) z;
+--------+-----------+--------+-----+
| deptno | dname     | loc    | cnt |
+--------+-----------+--------+-----+
|     10 | 教研部    | 北京   |   5 |
|     20 | 学工部    | 上海   |   5 |
|     30 | 销售部    | 广州   |   5 |
|     40 | 财务部    | 武汉   |   5 |
|     10 | 教研部    | 北京   |   6 |
|     20 | 学工部    | 上海   |   6 |
|     30 | 销售部    | 广州   |   6 |
|     40 | 财务部    | 武汉   |   6 |
|     10 | 教研部    | 北京   |   3 |
|     20 | 学工部    | 上海   |   3 |
|     30 | 销售部    | 广州   |   3 |
|     40 | 财务部    | 武汉   |   3 |
|     10 | 教研部    | 北京   |   1 |
|     20 | 学工部    | 上海   |   1 |
|     30 | 销售部    | 广州   |   1 |
|     40 | 财务部    | 武汉   |   1 |
+--------+-----------+--------+-----+
16 rows in set (0.00 sec)

从上述查询结果看到,会有相关数据的重复,和一些无用错误的数据,这样在两张表又一个相同的关联的字段deptno,通过这个字段来去除无用的数据(笛卡尔积)

select d.* ,z.cnt from dept d , (select deptno , count(*) cnt from emp group by deptno) z where d.deptno=z.deptno;

mysql> select d.* ,z.cnt from dept d , (select deptno , count(*) cnt from emp group by deptno) z where d.deptno=z.deptno;
+--------+-----------+--------+-----+
| deptno | dname     | loc    | cnt |
+--------+-----------+--------+-----+
|     10 | 教研部    | 北京   |   3 |
|     20 | 学工部    | 上海   |   5 |
|     30 | 销售部    | 广州   |   6 |
+--------+-----------+--------+-----+
3 rows in set (0.00 sec)

针对上述的编写使用的是mysql语言自有的编写方式,为了是sql语句在不同的数据库中同样可以使用我们需要在上述语言进行标准化的修改,即","用"inner join"来替代,"where"用"on"来替代,替代之后的sql语句为:

select d.* ,z.cnt from dept d inner join (select deptno , count(*) cnt from emp group by deptno) z on d.deptno=z.deptno;

mysql> select d.* ,z.cnt from dept d inner join (select deptno , count(*) cnt from emp group by deptno) z on d.deptno=z.deptno;
+--------+-----------+--------+-----+
| deptno | dname     | loc    | cnt |
+--------+-----------+--------+-----+
|     10 | 教研部    | 北京   |   3 |
|     20 | 学工部    | 上海   |   5 |
|     30 | 销售部    | 广州   |   6 |
+--------+-----------+--------+-----+
3 rows in set (0.00 sec)

总结:我们这里用到了多表查询中的内链接查询,涉及到的知识点有:内链接查询概念原理,inner join,on,笛卡尔积,如何去除笛卡尔积;

2. 列出所有员工的姓名及其直接上级的姓名。

分析:
列:姓名,上级姓名
表:emp
查询员工姓名和员工领导的编号:

select ename ,mgr from emp;

mysql> select ename ,mgr from emp;
+-----------+------+
| ename     | mgr  |
+-----------+------+
| 甘宁      | 1013 |
| 黛绮丝    | 1006 |
| 殷天正    | 1006 |
| 刘备      | 1009 |
| 谢逊      | 1006 |
| 关羽      | 1009 |
| 张飞      | 1009 |
| 诸葛亮    | 1004 |
| 曾阿牛    | NULL |
| 韦一笑    | 1006 |
| 周泰      | 1008 |
| 陈普      | 1006 |
| 庞统      | 1004 |
| 黄盖      | 1007 |
| 张三      | 1001 |
+-----------+------+
15 rows in set (0.00 sec)

查询编号和对应员工姓名

select ename , empno from emp;

mysql> select ename , empno from emp;
+-----------+-------+
| ename     | empno |
+-----------+-------+
| 甘宁      |  1001 |
| 黛绮丝    |  1002 |
| 殷天正    |  1003 |
| 刘备      |  1004 |
| 谢逊      |  1005 |
| 关羽      |  1006 |
| 张飞      |  1007 |
| 诸葛亮    |  1008 |
| 曾阿牛    |  1009 |
| 韦一笑    |  1010 |
| 周泰      |  1011 |
| 陈普      |  1012 |
| 庞统      |  1013 |
| 黄盖      |  1014 |
| 张三      |  1015 |
+-----------+-------+
15 rows in set (0.00 sec)

内联查询信息,在内联查询中会出现笛卡尔积,去除笛卡尔积

select e1.,e2. from (select ename ,mgr from emp) e1 inner join (select ename , empno from emp) e2 on e1.mgr=e2.empno;

mysql> select e1.*,e2.* from (select ename ,mgr from emp) e1 inner join (select ename , empno from emp) e2 on e1.mgr=e2.empno;
+-----------+------+-----------+-------+
| ename     | mgr  | ename     | empno |
+-----------+------+-----------+-------+
| 甘宁      | 1013 | 庞统      |  1013 |
| 黛绮丝    | 1006 | 关羽      |  1006 |
| 殷天正    | 1006 | 关羽      |  1006 |
| 刘备      | 1009 | 曾阿牛    |  1009 |
| 谢逊      | 1006 | 关羽      |  1006 |
| 关羽      | 1009 | 曾阿牛    |  1009 |
| 张飞      | 1009 | 曾阿牛    |  1009 |
| 诸葛亮    | 1004 | 刘备      |  1004 |
| 韦一笑    | 1006 | 关羽      |  1006 |
| 周泰      | 1008 | 诸葛亮    |  1008 |
| 陈普      | 1006 | 关羽      |  1006 |
| 庞统      | 1004 | 刘备      |  1004 |
| 黄盖      | 1007 | 张飞      |  1007 |
| 张三      | 1001 | 甘宁      |  1001 |
+-----------+------+-----------+-------+
14 rows in set (0.00 sec)

根据题目具体优化查询语句

select e1.ename '员工', e2.ename '领导' from (select ename ,mgr from emp) e1 inner join (select ename , empno from emp) e2 on e1.mgr=e2.empno;

mysql> select e1.ename '员工', e2.ename '领导' from (select ename ,mgr from emp) e1 inner join (select ename , empno from emp) e2 on e1.mgr=e2.empno;
+-----------+-----------+
| 员工      | 领导      |
+-----------+-----------+
| 甘宁      | 庞统      |
| 黛绮丝    | 关羽      |
| 殷天正    | 关羽      |
| 刘备      | 曾阿牛    |
| 谢逊      | 关羽      |
| 关羽      | 曾阿牛    |
| 张飞      | 曾阿牛    |
| 诸葛亮    | 刘备      |
| 韦一笑    | 关羽      |
| 周泰      | 诸葛亮    |
| 陈普      | 关羽      |
| 庞统      | 刘备      |
| 黄盖      | 张飞      |
| 张三      | 甘宁      |
+-----------+-----------+
14 rows in set (0.00 sec)

但是在查询中我们会发现'曾阿牛'出现在表中,则这里用到的则是外连接

select e1.ename '员工', ifnull(e2.ename ,'BOSS') '领导' from (select ename ,mgr from emp) e1 left outer join (select ename , empno from emp) e2 on e1.mgr=e2.empno;

mysql> select e1.ename '员工', ifnull(e2.ename ,'BOSS') '领导' from (select ename ,mgr from emp) e1 left outer join (select ename , empno from emp) e2 on e1.mgr=e2.empno;
+-----------+-----------+
| 员工      | 领导      |
+-----------+-----------+
| 甘宁      | 庞统      |
| 黛绮丝    | 关羽      |
| 殷天正    | 关羽      |
| 刘备      | 曾阿牛    |
| 谢逊      | 关羽      |
| 关羽      | 曾阿牛    |
| 张飞      | 曾阿牛    |
| 诸葛亮    | 刘备      |
| 曾阿牛    | BOSS      |
| 韦一笑    | 关羽      |
| 周泰      | 诸葛亮    |
| 陈普      | 关羽      |
| 庞统      | 刘备      |
| 黄盖      | 张飞      |
| 张三      | 甘宁      |
+-----------+-----------+
15 rows in set (0.01 sec)

总结:这道题目涉及到的是单张表的多次查询,还有就是对于寻找去除笛卡尔积的方法,外联查询的知识(左外链,右外链,全外链(mysql无法实现)),通过'曾阿牛'信息的空缺可以看出内链接,外链接查询的区别;

4. 列出受雇日期早于直接上级的所有员工的编号、姓名、部门名称。

列:员工编号empno,姓名ename deptno>emp 部门名称dname,deptno->dept
表:emp e1 ,emp e2,dept d
查询员工编号,姓名,领导编号,部门编号,入职日期(员工)

mysql> select empno,ename,mgr ,deptno ,hiredate from emp;
+-------+-----------+------+--------+------------+
| empno | ename     | mgr  | deptno | hiredate   |
+-------+-----------+------+--------+------------+
|  1001 | 甘宁      | 1013 |     20 | 2000-12-17 |
|  1002 | 黛绮丝    | 1006 |     30 | 2001-02-20 |
|  1003 | 殷天正    | 1006 |     30 | 2001-02-22 |
|  1004 | 刘备      | 1009 |     20 | 2001-04-21 |
|  1005 | 谢逊      | 1006 |     30 | 2001-09-28 |
|  1006 | 关羽      | 1009 |     30 | 2001-05-01 |
|  1007 | 张飞      | 1009 |     10 | 2001-09-01 |
|  1008 | 诸葛亮    | 1004 |     20 | 2007-04-19 |
|  1009 | 曾阿牛    | NULL |     10 | 2001-11-17 |
|  1010 | 韦一笑    | 1006 |     30 | 2001-09-08 |
|  1011 | 周泰      | 1008 |     20 | 2007-05-23 |
|  1012 | 陈普      | 1006 |     30 | 2001-12-03 |
|  1013 | 庞统      | 1004 |     20 | 2001-12-03 |
|  1014 | 黄盖      | 1007 |     10 | 2002-01-23 |
|  1015 | 张三      | 1001 |     50 | 2013-05-01 |
+-------+-----------+------+--------+------------+
15 rows in set (0.00 sec)

查询员工编号,姓名,入职日期(领导)

mysql> select empno,ename,hiredate from emp;
+-------+-----------+------------+
| empno | ename     | hiredate   |
+-------+-----------+------------+
|  1001 | 甘宁      | 2000-12-17 |
|  1002 | 黛绮丝    | 2001-02-20 |
|  1003 | 殷天正    | 2001-02-22 |
|  1004 | 刘备      | 2001-04-21 |
|  1005 | 谢逊      | 2001-09-28 |
|  1006 | 关羽      | 2001-05-01 |
|  1007 | 张飞      | 2001-09-01 |
|  1008 | 诸葛亮    | 2007-04-19 |
|  1009 | 曾阿牛    | 2001-11-17 |
|  1010 | 韦一笑    | 2001-09-08 |
|  1011 | 周泰      | 2007-05-23 |
|  1012 | 陈普      | 2001-12-03 |
|  1013 | 庞统      | 2001-12-03 |
|  1014 | 黄盖      | 2002-01-23 |
|  1015 | 张三      | 2013-05-01 |
+-------+-----------+------------+
15 rows in set (0.00 sec)

查询员工和领导信息集合表(去笛卡尔积)

mysql> select e1.empno,e1.ename,e1.hiredate,e1.mgr, e2.ename,e2.hiredate,e2.empno from emp e1 inner join emp e2 on e1.mgr=e2.empno;
+-------+-----------+------------+------+-----------+------------+-------+
| empno | ename     | hiredate   | mgr  | ename     | hiredate   | empno |
+-------+-----------+------------+------+-----------+------------+-------+
|  1001 | 甘宁      | 2000-12-17 | 1013 | 庞统      | 2001-12-03 |  1013 |
|  1002 | 黛绮丝    | 2001-02-20 | 1006 | 关羽      | 2001-05-01 |  1006 |
|  1003 | 殷天正    | 2001-02-22 | 1006 | 关羽      | 2001-05-01 |  1006 |
|  1004 | 刘备      | 2001-04-21 | 1009 | 曾阿牛    | 2001-11-17 |  1009 |
|  1005 | 谢逊      | 2001-09-28 | 1006 | 关羽      | 2001-05-01 |  1006 |
|  1006 | 关羽      | 2001-05-01 | 1009 | 曾阿牛    | 2001-11-17 |  1009 |
|  1007 | 张飞      | 2001-09-01 | 1009 | 曾阿牛    | 2001-11-17 |  1009 |
|  1008 | 诸葛亮    | 2007-04-19 | 1004 | 刘备      | 2001-04-21 |  1004 |
|  1010 | 韦一笑    | 2001-09-08 | 1006 | 关羽      | 2001-05-01 |  1006 |
|  1011 | 周泰      | 2007-05-23 | 1008 | 诸葛亮    | 2007-04-19 |  1008 |
|  1012 | 陈普      | 2001-12-03 | 1006 | 关羽      | 2001-05-01 |  1006 |
|  1013 | 庞统      | 2001-12-03 | 1004 | 刘备      | 2001-04-21 |  1004 |
|  1014 | 黄盖      | 2002-01-23 | 1007 | 张飞      | 2001-09-01 |  1007 |
|  1015 | 张三      | 2013-05-01 | 1001 | 甘宁      | 2000-12-17 |  1001 |
+-------+-----------+------------+------+-----------+------------+-------+
14 rows in set (0.01 sec)

筛选受雇日期早于直接上级的信息

mysql> select e1.empno,e1.ename,e1.hiredate,e1.mgr, e2.ename,e2.hiredate,e2.empno from emp e1 inner join emp e2 on e1.mgr=e2.empno and e1.hiredate<e2.hiredate;
+-------+-----------+------------+------+-----------+------------+-------+
| empno | ename     | hiredate   | mgr  | ename     | hiredate   | empno |
+-------+-----------+------------+------+-----------+------------+-------+
|  1001 | 甘宁      | 2000-12-17 | 1013 | 庞统      | 2001-12-03 |  1013 |
|  1002 | 黛绮丝    | 2001-02-20 | 1006 | 关羽      | 2001-05-01 |  1006 |
|  1003 | 殷天正    | 2001-02-22 | 1006 | 关羽      | 2001-05-01 |  1006 |
|  1004 | 刘备      | 2001-04-21 | 1009 | 曾阿牛    | 2001-11-17 |  1009 |
|  1006 | 关羽      | 2001-05-01 | 1009 | 曾阿牛    | 2001-11-17 |  1009 |
|  1007 | 张飞      | 2001-09-01 | 1009 | 曾阿牛    | 2001-11-17 |  1009 |
+-------+-----------+------------+------+-----------+------------+-------+
6 rows in set (0.00 sec)

整合部门信息

mysql> select e1.empno,e1.ename,e1.hiredate,e1.mgr, e2.ename,e2.hiredate,e2.empno ,d.dname from emp e1 inner join emp e2 inner join dept d on e1.mgr=e2.empno and e1.hiredate<e2.hiredate and e1.deptno=d.deptno;
+-------+-----------+------------+------+-----------+------------+-------+-----------+
| empno | ename     | hiredate   | mgr  | ename     | hiredate   | empno | dname     |
+-------+-----------+------------+------+-----------+------------+-------+-----------+
|  1001 | 甘宁      | 2000-12-17 | 1013 | 庞统      | 2001-12-03 |  1013 | 学工部    |
|  1002 | 黛绮丝    | 2001-02-20 | 1006 | 关羽      | 2001-05-01 |  1006 | 销售部    |
|  1003 | 殷天正    | 2001-02-22 | 1006 | 关羽      | 2001-05-01 |  1006 | 销售部    |
|  1004 | 刘备      | 2001-04-21 | 1009 | 曾阿牛    | 2001-11-17 |  1009 | 学工部    |
|  1006 | 关羽      | 2001-05-01 | 1009 | 曾阿牛    | 2001-11-17 |  1009 | 销售部    |
|  1007 | 张飞      | 2001-09-01 | 1009 | 曾阿牛    | 2001-11-17 |  1009 | 教研部    |
+-------+-----------+------------+------+-----------+------------+-------+-----------+
6 rows in set (0.00 sec)

优化查询字段

mysql> select e1.empno,e1.ename,e1.deptno, d.dname from emp e1 inner join emp e2 inner join dept d on e1.mgr=e2.empno and e1.hiredate<e2.hiredate and e1.deptno=d.deptno;
+-------+-----------+--------+-----------+
| empno | ename     | deptno | dname     |
+-------+-----------+--------+-----------+
|  1001 | 甘宁      |     20 | 学工部    |
|  1002 | 黛绮丝    |     30 | 销售部    |
|  1003 | 殷天正    |     30 | 销售部    |
|  1004 | 刘备      |     20 | 学工部    |
|  1006 | 关羽      |     30 | 销售部    |
|  1007 | 张飞      |     10 | 教研部    |
+-------+-----------+--------+-----------+
6 rows in set (0.00 sec)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容