多表联查时的条件筛选

        先举个例子,我们去买饼干,我想要的饼干是绿色威化饼干,这时候Left Join On()里就是“绿色”和“威化饼干”两个条件。必须先同时符合这两个条件,买回来绿色威化饼干,我们才能谈后续对于它的条件筛选:比如说找到方形的、圆形的、三角形的。

        但如果我们先只给On()传输一个“绿色”,我们买回来的是可能是绿色曲奇饼干、绿色苏打饼干、绿色夹心饼干等。这时再追加一个“威化饼干”的and条件,虽说也会找到一些“绿色威化饼干”,但是会出现许多多余的、错误的饼干,这都是我们不需要的,我们却费劲买回来了。更不要提后续对于饼干大小、形状等其他条件的筛选啦。

        理解了这个例子以后,再来看On、Where、And条件也不迟。

        在 mapper.xml中填写SQL语句,在<if>标签中加入and条件来拼接,但在拼接and之前要先有个where条件。可以写成where 1 = 1,再给后面拼接其他条件。如果不加where直接拼接and,编译器会认为and后的条件为联合查询时的条件,不能起到过滤作用。

select sl.create_time,
       sl.username,
       sl.operate_type,
       sl.log_content,
       sdi.item_text
from sys_log sl
left join sys_dict_item sdi
on (sl.operate_type = sdi.item_value and sdi.dict_id = "880a895c98afeca9d9ac39f29e67c13e"
        )
where 1 = 1
<if test="SysLogTest.username != null">
    and username like concat ('%', #{SysLogTest.username}, '%')
</if>
<if test="SysLogTest.selectCreateTime != null">
    and datediff(create_time, #{SysLogTest.selectCreateTime})= 0
</if>
<if test="SysLogTest.logContent != null">
    and log_content = #{SysLogTest.logContent}
</if>

         这里我们着重要注意的点是Left Join On()里的联查条件。在此处我们有两种写法,第一种是常规写法,我们先将两张表联合成一张临时表,然后再在其中根据and条件筛选数据:

left join sys_dict_item sdi
on (sl.operate_type = sdi.item_value)
where 1 = 1
and sdi.dict_id = "880a895c98afeca9d9ac39f29e67c13e"
and ......

        或者是在on中加入几个先决and条件,先根据on中的条件联合两张表生成一张临时表,然后再在这张临时表中根据and条件筛选:

left join sys_dict_item sdi
on (sl.operate_type = sdi.item_value and sdi.dict_id = "880a895c98afeca9d9ac39f29e67c13e")
where 1 = 1
and ......

        这样写实际上是有区别的,在联查操作中,会先根据Left Join On()中的条件合成一张临时表,再进行后续的查询。第一种写法只会根据 sl.operate_type = sdi.item_value 这个条件,合成临时表,再查询;第二种写法则需要同时符合两个条件,再合成临时表。看起来似乎两者并没有什么区别,但实际上会产生很大的偏差。

             

        这是按照第二种写法生成的正确数据,因为我们给item_text对应了我所需要的dict_id,先根据on()中的两个条件生成了数据表,再生成数据。再做后续的筛选操作,没有任何问题。

        但如果我们先生成临时表,表中item_text可能已经不是我所需要的item_text,它指向了错误的dict_id。生成数据时,也就完全不是我想要的,后续的任何操作也都会产生错误。

        一定要注意On、Where、And的使用顺序带来的差异。       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值