2017-02-10 206 views
2

我在优化(应该是)简单的SQL查询时遇到了问题,但时间有严重问题。我已经写了三次,但都没有成功。这是我原本希望能够工作的一个:INNER JOIN查询

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查询的INNER JOIN查询中)工作得很快,没有问题。当我在主SELECT选择查询(选择RSKADDR。*)的INNER JOIN中集成第二个SELECT查询时出现问题

那么看起来执行永远不会结束!

我尝试过其他的方式和同样的结果:

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 

这是荒谬的。这是一个简单的查询,不能让它工作。任何帮助将不胜感激。

+1

你能分享你的模式和数据吗 –

+0

嗨,谢谢你的回应。由于涉及隐私信息,遗憾的是无法共享数据。你想知道关于这个计划的什么?我能否帮助解释,而不分享整个模式? – Ankhnesmerira

+0

只能分享示例数据和模式不精确 –

回答

2

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); 
+0

非常感谢您的回复。你的代码更有意义,它更清洁。查询执行仍然花费太长时间,但我认为这是由于设计错误的模式。我想知道我是否应该使用临时表并对其进行选择? – Ankhnesmerira

+0

索引不起作用吗? –

+0

不幸的不是。 :( – Ankhnesmerira

0

从查询,你只需要RSKADDR数据,因此没有必要的INNER JOIN。您也可以使用EXISTS关键字。尝试以下查询

SELECT RSKADDR.* 
FROM EDW_BASE.RCI_RISK_ADDRESS RSKADDR 
WHERE EXISTS (
    SELECT 1 
    FROM EDW_BASE.RCI_COVER_RISK_MASTER RSKMASTER 
    WHERE EXISTS 
    (SELECT 1 
    FROM EDW_STG.STG_CIM_SVOM03 
    WHERE OUTSTANDING = 1 AND QUEUE = 'CIM Update for Contact Address') ADDR_WF 
    AND RSKMASTER.CONTACT_CODE = ADDR_WF.CONTACT_ID 
    AND 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 
) 
AND RSKMASTER.COVER_RISK_ID = RSKADDR.RISK_ID 
) 

注意:我没有测试过查询,因为没有可用的模式。

+0

语法错误不需要模式 – Strawberry