mysql 如何去除表连接查询出来的重复数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql 如何去除表连接查询出来的重复数据相关的知识,希望对你有一定的参考价值。

参考技术A 找到出现重复的原因,是笛卡尔集还是错误数据导致的。
笛卡尔集,一般在连接后用group by 或是distinct 解决;具体也要看情况
错误数据,那就找到错误数据的关键字段,在连接前就屏蔽掉

MySQL—— 连接查询

8. 连接查询

8.1 distinct

  distinct:把查询结果去除重复记录。注意:原表数据不会被修改,只是查询结果去重。

  distinct只能出现在所有字段的最前方:select distinct job from emp;

  select ename,distinct job from emp;会报错。


  distinct出现在job,deptno两个字段之前,表示两个字段联合起来去重:select distinct job,deptno from emp;

  • 统计一下工作岗位的数量:select count(distinct job) from emp;

8.2 什么是连接查询

  从一张表中单独查询,称为单表查询
  emp表和dept表联合起来查询数据,从emp表中取员工名字,从dept表中取部门名字。这种跨表查询,多张表联合起来查询数据,被称为连接查询

8.3 连接查询的分类

  • 根据语法的年代分类:
    SQL92:1992年的时候出现的语法
    SQL99:1999年的时候出现的语法(重点)

  • 根据表连接的方式分类:
    ⋄ \\diamond 内连接:
      等值连接
      非等值连接
      自连接
    ⋄ \\diamond 外连接:
      左外连接(左连接)
      右外连接(右连接)
    ⋄ \\diamond 全连接

8.4 笛卡尔积现象

  问题: 当两张表进行连接查询时,没有任何条件的限制会发生什么现象?

  • 查询每个员工所在部门名称
    从员工信息表查询员工姓名和部门编号: select ename,deptno from emp;


    从部门信息表查询所有信息:select * from dept;


    查询每个员工所在部门名称:select ename, dname from emp, dept;(两张表连接没有任何条件限制)


    一共14 * 4 = 56条记录。

  当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积,这种现象被称为:笛卡尔积现象
  怎么避免笛卡尔积现象?连接时加条件,满足这个条件的记录被筛选出来!

  • 当员工信息表的部门编号和部门信息表的部门编号相等时,查询每个员工所在部门名称:
select 
	emp.ename, dept.dname
from 
	emp, dept
where
	emp.deptno = dept.deptno;


  表起别名很重要,可以提高效率。

select 
	e.ename,d.dname 
from 
	emp e, dept d
where
	e.deptno = d.deptno; //SQL92语法


  思考: 最终查询的结果条数是14条,但是匹配的过程中,匹配的次数减少了吗?
  没有,还是56次,只不过进行了四选一,次数没有减少。

  注意: 通过笛卡尔积现象得出,表的连接次数越多,效率越低,所以要尽量避免表的连接次数。

  以上加入指定条件的查询也称为 “内连接”,只查询相等的数据(连接条件相等的数据)。

8.5 内连接

8.5.1 等值连接

  等值连接: 条件是等量关系。

  • 查询每个员工所在部门名称,显示员工名和部门名
    emp edept d表进行连接,条件是:e.deptno = d.deptno
  • SQL92语法:
select 
	e.ename,d.dname
from
	emp e, dept d
where
	e.deptno = d.deptno;


  SQL92的缺点:结构不清晰,表的连接条件和后期进一步筛选的条件,都放到了where后面。

  • SQL99语法:
select 
	e.ename,d.dname
from
	emp e
join
	dept d
on
	e.deptno = d.deptno;


  也可以写成如下形式:

select 
	e.ename,d.dname
from
	emp e
inner join  //inner可以省略(带着inner可读性更好!!!一眼就能看出来是内连接)
	dept d
on
	e.deptno = d.deptno;  // 条件是等量关系,所以被称为等值连接。

  SQL99的优点:表连接的条件是独立的,连接之后,如果还需要进一步筛选,再往后继续添加where
  SQL99的语法

select 
	...
from
	a
join
	b
on
	a和b的连接条件
where
	筛选条件

  SQL92 语法和 SQL99 语法的区别:99 语法可以做到表的连接和查询条件分离,特别是多个表进行连接的时候,会比SQL92更清晰。

8.5.2 非等值连接

  非等值连接: 条件不是一个等量关系。

  • 找出每个员工的薪资等级,要求显示员工名、薪资、薪资等级
    查询员工信息表所有信息:select * from emp;


    查询薪水等级信息表所有信息:select * from salgrade;


    找出每个员工的薪资等级,要求显示员工名、薪资、薪资等级:
select 
	e.ename, e.sal, s.grade
from
	emp e
join
	salgrade s
on
	e.sal between s.losal and s.hisal;  // 条件不是一个等量关系,称为非等值连接。

8.5.3 自连接

  • 查询员工的上级领导,要求显示员工名和对应的领导名
    查询员工信息表的员工编号、员工姓名、上级领导编号信息:select empno,ename,mgr from emp;


    技巧: 一张表看成两张表。
    emp a 员工表
    emp b 领导表
    查询员工的上级领导,要求显示员工名和对应的领导名:
select 
	a.ename as '员工名', b.ename as '领导名'
from
	emp a
join
	emp b
on
	a.mgr = b.empno;  //员工的领导编号 = 领导的员工编号

  以上称为“自连接”,只有一张表连接,具体的查询方法,把一张表看作两张表即可,如以上示例:第一个表 emp a 代表了员工表,emp b 代表了领导表,相当于员工表和部门表一样。

8.6 外连接

  查询员工信息表所有信息:select * from emp;


  查询部门信息表所有信息:select * from dept;


  内连接: A和B连接,AB两张表没有主次关系,是平等的。

select 
	e.ename,d.dname
from
	emp e
join
	dept d
on
	e.deptno = d.deptno;  //内连接的特点:完成能够匹配上这个条件的数据查询出来。

8.6.1 右外连接

  外连接(右外连接):

select 
	e.ename,d.dname
from
	emp e 
right join 
	dept d
on
	e.deptno = d.deptno;


  也可以写成如下形式:

// outer是可以省略的,带着可读性强。
select 
	e.ename,d.dname
from
	emp e 
right outer join 
	dept d
on
	e.deptno = d.deptno;

  right代表什么:表示将join关键字右边的这张表看成主表,主要是为了将这张表的数据全部查询出来,捎带着关联查询左边的表。
  在外连接当中,两张表连接,产生了主次关系。

8.6.2 左外连接

  外连接(左外连接):

select 
	e.ename,d.dname
from
	dept d 
left join 
	emp e
on
	e.deptno = d.deptno;


  也可以写成如下形式:

// outer是可以省略的,带着可读性强。
select 
	e.ename,d.dname
from
	dept d 
left outer join 
	emp e
on
	e.deptno = d.deptno;

  带有right的是右外连接,又叫做右连接。
  带有left的是左外连接,又叫做左连接。
  任何一个右连接都有左连接的写法,任何一个左连接都有右连接的写法。
  左外连接(左连接)和右外连接(右连接)的区别:左连接以左面的表为准和右边的表比较,和左表相等的不相等都会显示出来,右表符合条件的显示,不符合条件的不显示;右连接恰恰相反。

  思考: 外连接的查询结果条数一定是 >= 内连接的查询结果条数? 正确。

  • 查询每个员工的上级领导,要求显示所有员工的名字和领导名:
select 
	a.ename as '员工名', b.ename as '领导名'
from
	emp a
left join
	emp b
on
	a.mgr = b.empno; 

8.7 三张表、四张表怎么连接

  语法:

select 
	...
from
	a
join
	b
on
	a和b的连接条件
join
	c
on
	a和c的连接条件
right join
	d
on
	a和d的连接条件

  一条SQL中内连接和外连接可以混合,都可以出现!

  • 找出每个员工的部门名称以及工资等级,要求显示员工名、部门名、薪资、薪资等级:
select 
	e.ename,e.sal,d.dname,s.grade
from
	emp e
join
	dept d
on 
	e.deptno = d.deptno  // e表和d表的连接条件:e表的员工部门编号要等于d表的部门编号
join
	salgrade s
on
	e.sal between s.losal and s.hisal;  // e表和s表的连接条件:e表的员工薪资要在s表的losal值和hisal值之间

  • 找出每个员工的部门名称以及工资等级还有上级领导,要求显示员工名、领导名、部门名、薪资、薪资等级:
select 
	e.ename,e.sal,d.dname,s.grade,l.ename
from
	emp e
join
	dept d
on 
	e.deptno = d.deptno  // e表和d表的连接条件:e表的员工部门编号要等于d表的部门编号
join
	salgrade s
on
	e.sal between s.losal and s.hisal  // e表和s表的连接条件:e表的员工薪资要在s表的losal值和hisal值之间
left join  //要求找出每个员工的部门名称以及工资等级,捎带找出上级领导,所以前面的是主表,使用左外连接
	emp l
on
	e.mgr = l.empno;   //e表和l表的连接条件:e表的领导编号 = l表的员工编号

以上是关于mysql 如何去除表连接查询出来的重复数据的主要内容,如果未能解决你的问题,请参考以下文章

oracle如何查重复数据并显示出来?

请教大家!mysql查询结果,过滤重复数据?

oracle查重复数据并显示出来

mysql连接查询

MySQL—— 连接查询

mysql-数据库查询语句汇总