外键 左连接 和自连接的用法

1 在创建表时加入外键

表1

CREATE table department(

id  int primary key auto_increment,
name varchar(20) not null,
description varchar(100)
)

表2
CREATE table employee(
id int PRIMARY key auto_increment,
name VARCHAR(20) not null,
dep_id  int not null,
description varchar(100),

CONSTRAINT waijianName FOREIGN KEY (dep_id)
REFERENCES  department(id)

)

2

内连接:只列出匹配的记录

左外连接:左表列出全部,右表只列出匹配的记录。

例子

SELECT
a.id id ,
c.id userId,
b.user_auth_name custName,
c.username phone,
b.identity_type shenfen,
    a.updated_time updatedTime ,
    a.`status` status,
    
a.category_type type,
    d.full_name subjectName,
    e.zh_name brandChina,
    e.en_name brandEnglish,
a.updated_by  updateName

FROM
user_auth_category a
LEFT JOIN user_auth_info b ON a.user_auth_info_id = b.id
LEFT JOIN `user` c on b.user_id=c.id
LEFT JOIN `subject` d on a.category_id = d.id and a.category_type=1
left join brand e on a.category_id = e.id and a.category_type=2

WHERE a.is_active = 1
AND
    a.is_admin = 1
AND a. STATUS IN (1, 10,15)
     <if test="userId != null and userId != '' " >
      and b.user_id = #{userId,jdbcType=BIGINT}
    </if>
<if test="custName != null and custName!=''" >
      and b.user_auth_name LIKE CONCAT('%',#{custName,jdbcType=VARCHAR},'%')
    </if>
    <if test="updateName != null and updateName!=''" >
      and a.updated_by LIKE CONCAT('%',#{updateName,jdbcType=VARCHAR},'%')  and a.status != 1
    </if>
    <if test="status != null and status != '' " >
      and a.status = #{status,jdbcType=TINYINT}
    </if>
    <if test="shenfen != null and shenfen != ''" >
      and b.identity_type = #{shenfen,jdbcType=TINYINT}
    </if>
    <if test="name != null and name!=''" >
      and (d.full_name LIKE CONCAT('%',#{name,jdbcType=VARCHAR},'%')
    
      or e.zh_name LIKE CONCAT('%',#{name,jdbcType=VARCHAR},'%')
    
      or e.en_name LIKE CONCAT('%',#{name,jdbcType=VARCHAR},'%'))
    </if>
    <if test="phone != null and phone!=''" >
      and c.username = #{phone,jdbcType=VARCHAR}
    </if>
    <if test="endTime!=null and endTime!=''">
      <![CDATA[   and DATE_FORMAT(a.updated_time, '%Y-%m-%d')<=  DATE_FORMAT(#{endTime}, '%Y-%m-%d')   ]]>
    </if>
    <if test="startTime!=null and startTime!=''">
      <![CDATA[   and DATE_FORMAT(a.updated_time, '%Y-%m-%d')>=  DATE_FORMAT(#{startTime}, '%Y-%m-%d')   ]]>
    </if>
    ORDER BY CASE a.status  WHEN '1 ' THEN 1 WHEN '15' THEN 2 WHEN '10' THEN 3 END,a.updated_time DESC
    <if test="offset != null and max != null" >
      limit ${offset},${max}
    </if>

说明:多表连接查询:先对第一个和第二个表按照两表连接做查询,然后用查询结果和第三个表做连接查询,以此类推,直到所有的表都连接上为止,最终形成一个中间的结果表,然后根据WHERE条件过滤中间表的记录,并根据SELECT指定的列返回查询结果。
理解SQL查询的过程是进行SQL优化的理论依据。

ON后面的条件(ON条件)和WHERE条件的区别:
ON条件:是过滤两个链接表笛卡尔积形成中间表的约束条件。
WHERE条件:在有ON条件的SELECT语句中是过滤中间表的约束条件。在没有ON的单表查询中,是限制物理表或者中间查询结果返回记录的约束。在两表或多表连接中是限制连接形成最终中间表的返回结果的约束。
从这里可以看出,将WHERE条件移入ON后面是不恰当的。推荐的做法是:
ON只进行连接操作,WHERE只过滤中间表的记录。


小结 :左连接查询出主表的全部数据 ,多个left join时一步步去生成中间过滤表,最后要加where条件语句进行过滤筛选,得出所需结果。


右外连接:右表列出全部,左表只列出匹配的记录。

自连接参与连接的表都是同一张表。(通过给表取别名虚拟出两张表)

例子:

注:非常重要,在JavaWeb中的目录树中用的特别多。

举例:查询出员工姓名和其leader的姓名(类似于求节点及其父节点)

我们来详细解释一下上面的代码。对于同一张employee表,我们把e1作为员工表,e2作为领导表。首先把全部的员工列出来(基于左外连接),然后找到我们所需要的条件:员工的经理id(e1.leader)等于经理表的id(e2.id)

 

举例:查询出所有leader的姓名。

分析的道理同上。

其实,上面的两个查询结果都是下面这个查询结果的一部分:

 


八、总结
连接查询是SQL查询的核心,连接查询的连接类型选择依据实际需求。如果选择不当,非但不能提高查询效率,反而会带来一些逻辑错误或者性能低下。下面总结一下两表连接查询选择方式的依据:
1、 查两表关联列相等的数据用内连接。
2、 Col_L是Col_R的子集时用右外连接。
3、 Col_R是Col_L的子集时用左外连接。
4、 Col_R和Col_L彼此有交集但彼此互不为子集时候用全外。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值