2017-02-10 7 views
2

У меня возникли проблемы с оптимизацией (должен быть) простого SQL-запроса, но с серьезной проблемой с синхронизацией. Я написал это три раза, и никто из них не работает. Вот оригинал один я надеялся на работу:INNER JOIN query

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 (в запросе INNER JOIN первого и основного запроса SELECT) работает без проблем. Проблема возникает, когда я интегрирую второй запрос SELECT внутри INNER JOIN основного запроса 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 

Это абсурдно. это такой простой запрос и не может заставить его работать. Любая помощь будет принята с благодарностью.

+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