mysql exists 使用的意义

exists 方法 判断存在,

通常我们会碰到 这种 业务 需求,查询A表中的字段的时候,查询条件涉及到了 B 表中的字段,比如:

A表:

id    username   password         age

1        dd                123                  34

2         gg               234                  23

3         hh               908                  45

4          uu              987                  30

。。。

B表

id        sex           userId    

1          男              1

2           女              2

3          男              3

4          男              4

。。。

C表

id    role        userid

1      经理        1

2      老板        2

3      经理        3

 

A 表为主表, B表为 子表  外键 userid   与 主表关联,C表为子表 外键为 userid

已有的业务需求:查询 姓名 ,性别,  角色

select  a.name ,(select b.sex from B b where b.userid = a.id)  sex, (select c.role from C c where c.userid = a.id ) role   from A a  

我们在公司经常遇到在别人的sql进行修改,    真实的sql 很有可能几百行,很有 可能 会关联很多 表,此时突然加一人需求条件,根据 性别查询,此时 我们首先想到的是,原来的sql 尽量 不要大修改,因为很关关联关系也不是很明白,首先观察到 sex  字段是一个 子查询,在条件中 要按照 sex 进行过滤, 我们在where 后面不能直接 引用 sex  字段,这是也 不能在 from后面追加 B  表, 这时 exists 就可以拍到用场了 ,sql如下:

select  a.name ,(select b.sex from B b where b.userid = a.id)  sex, (select c.role from C c where c.userid = a.id ) role   from A a   where exists( select 0 from B b where b.userid = a.id and b.sex  ='男')  

我们在  实际开发中 很多的 时候 都会 用到 exists  关键字 进行优化sql,   

通常情况为 两种: 一种是 select中 有子查询 加入 输出字段为  zcx , 并且在 在 条件中需要这个 字段进行判断, 这时我们可以 利用exists 进行过滤。这时很巧妙的。

                            第二种是: sql 进行优化的时候,两张表的 数据太大,本人在实际的开发中实际的编写sql 中 有两 张 表,我记得一张表为 一亿多的数据 ,这里七个别名 为 A ,另一张表为 6千万的数据,这里七个别名 为 B ,而 B表需要先查询一次, 并且按照外键 和A 表进行关联, 然后将查询的结果 看作另一张表,再和A表关联, 好啦逻辑有点复杂 直接把sql  贴出来:

with cbizvivew as(
(select min(decode(cbiz_event,
                          'FFOP_UME_WEB_SHIPPING_WAIT',
                          cbiz_event_time,
                          null)) as firstwait, ---第一次等待时间 用于前端判断条件  
               min(decode(cbiz_event,
                          'FFOP_UME_WEB_SHIPPING_ACCEPT',
                          cbiz_event_time,
                          null)) as firstaccpt, ----第一次确认时间  用于前端判断条件
               min(decode(cbiz_event,
                          'FFOP_UME_WEB_SHIPPING_REJECT',
                          cbiz_event_time,
                          null)) as firstreject, ----第一次拒绝时间  用于前端判断条件
               
               min(decode(cbiz_event,
                          'FFOP_UME_WEB_SHIPPING_WAIT',
                          cbiz_event_time,
                          'FFOP_UME_WEB_SHIPPING_ACCEPT',
                          cbiz_event_time,
                          'FFOP_UME_WEB_SHIPPING_REJECT',
                          cbiz_event_time,
                          null)) as minbktime, ----第一次设置订舱状态时间
               
               min(decode(cbiz_event,
                          'FFOP_UME_WEB_SHIPPING_WAIT',
                          CBIZ_ID,
                          'FFOP_UME_WEB_SHIPPING_ACCEPT',
                          CBIZ_ID,
                          'FFOP_UME_WEB_SHIPPING_REJECT',
                          CBIZ_ID,
                          null)) as minid, ----第一次设置订舱状态时间          
               
               max(cbiz_event_time) as fourEvntFirstTime, ---4个事件中最新的那个时间
               max(decode(cbiz_event,
                          'EWEB_ORDER_CHANGED',
                          cbiz_event_time,
                          null)) as endoc, -----最新的一次订舱修改的时间
               
               max(decode(cbiz_event,
                          'FFOP_UME_WEB_SHIPPING_WAIT',
                          cbiz_event_time,
                          null)) as endwait, ---最新的一次等待时间
               max(decode(cbiz_event,
                          'FFOP_UME_WEB_SHIPPING_ACCEPT',
                          cbiz_event_time,
                          null)) as endaccpt, ----最新的一次确认时间
               max(decode(cbiz_event,
                          'FFOP_UME_WEB_SHIPPING_REJECT',
                          cbiz_event_time,
                          null)) as endreject, ---最新的一次拒绝时间
               
               cbiz_consign_id as cbiz_consign_id --- 运编号
        
          from cbiztrace a
         where a.cbiz_org_id = '83'
           and a.cbiz_event in ('FFOP_UME_WEB_SHIPPING_ACCEPT',
                                'FFOP_UME_WEB_SHIPPING_WAIT',
                                'FFOP_UME_WEB_SHIPPING_REJECT',
                                'EWEB_ORDER_CHANGED')
           and exists
         (Select 1
                  from fconsign fcsg
                 where fcsg.FCSG_ORG_ID = '83'
                   and a.cbiz_consign_id = fcsg.FCSG_CONSIGN_ID
                   
                   and fcsg.FCSG_ETD> to_date('2018-07-17 18:10:05','yyyy-mm-dd hh24:mi:ss')         -- E T D
             and fcsg.FCSG_ETD< to_date('2018-08-17 18:10:05','yyyy-mm-dd hh24:mi:ss')
         
             and fcsg.FCSG_CREATE_TIME > to_date('2018-07-17 18:10:05','yyyy-mm-dd hh24:mi:ss')      --创建日期
             and fcsg.FCSG_CREATE_TIME< to_date('2018-08-17 18:10:05','yyyy-mm-dd hh24:mi:ss')
          
             /*and fcsg.fcsg_vessel_en = 'KOTA PERDANA'                                                --船名航次
             and fcsg.fcsg_voyage_en = '0003E'*/
          )

                  
         group by cbiz_consign_id)
)
select 
        
      cbiz.firstaccpt, cbiz.firstwait ,cbiz.firstreject,

       FCSG_CONSIGN_ID,                                    --- 运编号
       FCSG_BO_NO,                                         --- 提单号    MB/ L NO                        1
       FCSG_BOOKING_AGENT,                                 --- 订舱代理代码,对应前台的舱位公司           2
       FCSG_VESSEL_EN,                                     --- 英文船名                                  3
       FCSG_ETD,                                           --- 船期   预离日期(出口)或到港日期(进口) 4
       FCSG_CUST_CSG_NO,                                   --- 客户业务号                                5
       FCSG_CONSIGN_DEPT,                                  -- 委托单位  客户供应商行信息编号,类型为客户 6
       FCSG_PAYMODE_ID,                                    --- 付款方式                                  7
       FCSG_TERM_ID,                                       --- 运输条款                                  8
       FCSG_BOK_CONTRACT_NO,                               --- 订舱协议号                                9
       FCSG_VOYAGE_EN,                                     --- 航次                                      10
       FCSG_SHIPPING_LINE_TRADE,                           --- 船公司航线                                11
       ---rst.CACC_BL_CUT_TIME,                             --- 提单截单时间                             12
       FCSG_DISCHARGE_PORT_CODE,                            --- 卸货港                                   13
       FCSG_DELIVERY_PLACE_CODE,                            --- 交货地                                   14
       
       hy_ff_utility_pkg.F_GET_CONSIGN_CNT_TYPE_QTY(fcsg.FCSG_CONSIGN_ID,
                                                            1) ctcn,   ---FCTP_CNT_TYPE ||'*'|| FCTP_CNT_COUNT 箱型箱量 15
       FCSG_CONTACTOR,                                      --- 客户联系人                               16
       FCSG_CONSIGN_TYPE,                                   --- 托运类型                                 17
       (select FCCI_IS_DANGER
                  from fconsigncargoinfo fio
                 where fio.FCCI_CONSIGN_ID = fcsg.FCSG_CONSIGN_ID 
                   and fio.FCCI_TYPE = 1
                   and rownum = 1) as FCCI_IS_DANGER,       --- 是否危险品                               18
       (select FCTP_IS_SOC
                  from fcontainerprepare fp
                 where fp.FCTP_CONSIGN_ID = fcsg.FCSG_CONSIGN_ID
                   and rownum = 1) issoc,                                 ---     是否SOC箱              19
       FCSG_REMARK,                                         --- 订舱备注                                 20
       FCSG_CREATE_TIME,                                     --- 创建时间                                21
       cbiz.minbktime  AS first_one_set_time,                ---   第 一次设置订舱状态时间               22
       (select CREATOR
                  from  cbiztrace cb
                 where cb.CBIZ_ID = cbiz.minid
                   and rownum = 1) AS CREATOR,            ---创建人                                     23
       ---当创建时间≤15:00,且第一次设置订舱状态的日期=创建日期,则判定为Y
       ---当创建时间>15:00,且第一次设置订舱状态的日期=创建日期+1个工作日,则判定为Y
       ---当创建时间≤15:00,且第一次设置订舱状态的日期>创建日期,则判定为N
       ---当创建时间>15:00,且第一次设置订舱状态的日期>创建日期+1个工作日,则判定为N
       (case
         when to_char(FCSG_CREATE_TIME, 'hh24:mi:ss') <= '15:00' and
              to_char(cbiz.minbktime, 'yyyy-mm-dd') =
              to_char(FCSG_CREATE_TIME, 'yyyy-mm-dd') then
         
          'Y'
         when to_char(FCSG_CREATE_TIME, 'hh24:mi:ss') > '15:00' and
              to_char(cbiz.minbktime, 'yyyy-mm-dd') =
              to_char(FCSG_CREATE_TIME + 1, 'yyyy-mm-dd') then
          'Y'
       
         when to_char(FCSG_CREATE_TIME, 'hh24:mi:ss') <= '15:00' and
              to_char(cbiz.minbktime, 'yyyy-mm-dd') >
              to_char(FCSG_CREATE_TIME, 'yyyy-mm-dd') then
          'N'
         when to_char(FCSG_CREATE_TIME, 'hh24:mi:ss') > '15:00' and
              to_char(cbiz.minbktime, 'yyyy-mm-dd') >
              to_char(FCSG_CREATE_TIME + 1, 'yyyy-mm-dd') then
          'N'
         else
          ' '
       end) WHETHER_FINAL_STATE_COMPLETED,                          ---是否在规定时间内完成状态设置 24
       (case cbiz.fourEvntFirstTime
         when cbiz.endaccpt then
          '订舱确认'
         when cbiz.endwait then
          '订舱等待'
         when cbiz.endreject then
          '订舱失败'
         when cbiz.endoc then
          '订舱修改'
         else
          ' '
       end) AS FINALS_STATE                                                          --- 最终状态25   

 
  from FCONSIGN fcsg,cbizvivew cbiz
 where cbiz.cbiz_consign_id = fcsg.FCSG_CONSIGN_ID 
 
              /*and cbiz.firstaccpt    > to_date('2015-07-17 18:10:05','yyyy-mm-dd hh24:mi:ss')    --订舱确认
              and cbiz.firstaccpt  < to_date('2018-08-17 18:10:05','yyyy-mm-dd hh24:mi:ss')
              */
             /* and cbiz.firstwait  > to_date('2015-07-17 18:10:05','yyyy-mm-dd hh24:mi:ss') --订舱等待
              and cbiz.firstwait  < to_date('2015-08-17 18:10:05','yyyy-mm-dd hh24:mi:ss')  
                
              and cbiz.firstreject  > to_date('2015-07-17 18:10:05','yyyy-mm-dd hh24:mi:ss') --订舱失败
              and cbiz.firstreject  < to_date('2015-08-17 18:10:05','yyyy-mm-dd hh24:mi:ss')*/

 

大家注意 : 红色的  查询条件 被注释掉, 然后在蓝色的地方进行 使用exists 进行过滤,这里我们可以 知道 先用exists 进行过滤 掉一定的数据,并且是按照索引  ,效率 是非常的高的。而红色的地方,则在 cbizvivew 中会 进行全表扫描,这样的效率是 非常慢的。 所以 我们在 sql  中 要学会 用exists 进行优化。。。。。。。。。

你可能感兴趣的:(sql数据库)