我在优化一个(应该是)简单的SQL查询时遇到了问题,但在时间安排上遇到了严重的问题。我写了三遍都没用。这是我原本希望工作的:

SELECT RSKADDR.*
FROM EDW_BASE.RCI_RISK_ADDRESS RSKADDR
INNER JOIN (
  SELECT DISTINCT COVER_RISK_ID
  FROM  EDW_BASE.RCI_COVER_RISK_MASTER RSKMASTER
  INNER JOIN
  (SELECT DISTINCT CONTACT_ID, FOLLOW_UP_DATE
  FROM EDW_STG.STG_CIM_SVOM03
  WHERE OUTSTANDING = 1 AND QUEUE = 'CIM Update for Contact Address') ADDR_WF
  ON RSKMASTER.CONTACT_CODE = ADDR_WF.CONTACT_ID
  WHERE RSKMASTER.IS_STORNO != 1
        AND RSKMASTER.PRODUCT_CODE = 'HOME'
        AND  ADDR_WF.FOLLOW_UP_DATE >= RSKMASTER.COVER_EFF_START_DATE
        AND RSKMASTER.POLICY_STATUS_CODE = 'POLICY'
        AND ADDR_WF.FOLLOW_UP_DATE <= RSKMASTER.COVER_EFF_END_DATE
  ) ACTVRSK
ON ACTVRSK.COVER_RISK_ID = RSKADDR.RISK_ID

第一个内部连接中的代码一直快速工作到最后。也就是说,第二个SELECT查询(在第一个和主SELECT查询的内部连接查询中)工作得很快,没有问题。当我将第二个SELECT查询集成到主SELECT查询(SELECT RSKADDR.*)的内部连接中时,问题就出现了
看来行刑是永无止境的!
我尝试了其他方法,结果一样:
SELECT RSKADDR.*
FROM EDW_BASE.RCI_RISK_ADDRESS RSKADDR

INNER JOIN EDW_BASE.RCI_COVER_RISK_MASTER RSKMASTER
ON RSKMASTER.COVER_RISK_ID = RSKADDR.RISK_ID
   AND RSKMASTER.IS_STORNO != 1
   AND RSKMASTER.PRODUCT_CODE = 'HOME'
   AND RSKMASTER.POLICY_STATUS_CODE = 'POLICY'

INNER JOIN EDW_STG.STG_CIM_SVOM03 ADDR_WF
ON OUTSTANDING = 1 AND QUEUE = 'CIM Update for Contact Address'
   AND RSKMASTER.CONTACT_CODE = ADDR_WF.CONTACT_ID
   AND ADDR_WF.FOLLOW_UP_DATE >= RSKMASTER.COVER_EFF_START_DATE
   AND ADDR_WF.FOLLOW_UP_DATE <= RSKMASTER.COVER_EFF_END_DATE

太荒谬了。这是一个如此简单的查询,无法让它工作。任何帮助都将不胜感激。

最佳答案

DISTINCT是一个昂贵的操作,很少需要。它通常表示数据库设计不好或查询写得不好。在您的查询中,您甚至重复执行此操作;这看起来不太好。
第二个查询看起来好多了。正如您所说,您得到的结果一样,第一个查询中的DISTINCT显然是多余的。
我看到你在做连接,但你所选择的只是一个表中的数据。那为什么要加入呢?从需要数据的表中进行选择,并将条件放在其所属的WHERE中。
下面的查询可能更快,因为它清楚地显示我们只是检查是否在其他表中找到匹配项。但是,MySQL在IN子句中的表现并不太好,这可能取决于您使用的版本。

select *
from edw_base.rci_risk_address
where risk_id in
(
  select rm.cover_risk_id
  from edw_base.rci_cover_risk_master rm
  where rm.is_storno <> 1
    and rm.product_code = 'HOME'
    and rm.policy_status_code = 'POLICY'
    and exists
    (
      select *
      from edw_stg.stg_cim_svom03 adr
      where adr.contact_id      = rm.contact_code
        and adr.follow_up_date >= rm.cover_eff_start_date
        and adr.follow_up_date <= rm.cover_eff_end_date
        and adr.outstanding = 1
        and adr.queue = 'CIM Update for Contact Address'
    )
);

不管怎样,对于您的第二个查询或我的第二个查询,我认为以下索引将有所帮助:
create index idx1 on rci_cover_risk_master
(
   product_code,
   policy_status_code,
   is_storno,
   contact_code,
   cover_eff_start_date,
   cover_eff_end_date,
   cover_risk_id
);

create index idx2 on stg_cim_svom03
(
  contact_id,
  follow_up_date,
  outstanding,
  queue
);

create index idx3 on rci_risk_address(risk_id);

关于mysql - INNER JOIN查询,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42153740/

10-09 08:22
查看更多