我在优化一个(应该是)简单的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/