如何解决如何重写此Oracle查询以使用有效的CTE
我有一个查询,希望通过使用with
子句来改进。我尝试了一个下面的变体,但是我只能降低一点成本。我该如何重写查询的主要部分,即联接的主要部分仅使用一次with子句记住,同时要记住,对于第二个子集,我有这个附加过滤器AND WS.CODE ='S_WLM_WL_013'
?
任何想法都会受到赞赏。
查询是
SELECT
CASE
WHEN ( SELECT COUNT(*)
FROM EXIM1B.GER_CUSTOMER_ONBOARDING GCO
INNER JOIN EXIM1B.ALERT_HEADER AH
ON AH.AT_ID=GCO.WLM_TRANSACTION_ID
INNER JOIN EXIM1B.WORKFLOW_STATUSES WS
ON AH.WW_STATUS_CODE =WS.CODE
WHERE GCO.MESSAGE_ID =:1
AND GCO.IDENTIFICATOR_ID=
(SELECT MIN(IDENTIFICATOR_ID)
FROM EXIM1B.GER_CUSTOMER_ONBOARDING
WHERE MESSAGE_ID=:1
)
) =
(SELECT COUNT(*)
FROM EXIM1B.GER_CUSTOMER_ONBOARDING GCO
INNER JOIN EXIM1B.ALERT_HEADER AH
ON AH.AT_ID=GCO.WLM_TRANSACTION_ID
INNER JOIN EXIM1B.WORKFLOW_STATUSES WS
ON AH.WW_STATUS_CODE =WS.CODE
AND WS.CODE ='S_WLM_WL_013'
WHERE GCO.MESSAGE_ID =:1
AND GCO.IDENTIFICATOR_ID=
(SELECT MIN(IDENTIFICATOR_ID)
FROM EXIM1B.GER_CUSTOMER_ONBOARDING
WHERE MESSAGE_ID=:1
)
)
THEN 'OK'
ELSE null END AS StatusAlert FROM DUAL
我尝试过这个
with t as ( SELECT MIN(IDENTIFICATOR_ID) as minval,message_id FROM EXIM1B.GER_CUSTOMER_ONBOARDING WHERE MESSAGE_ID=:1 group by message_id )
SELECT
CASE
WHEN ( SELECT COUNT(*)
FROM EXIM1B.GER_CUSTOMER_ONBOARDING GCO inner join t on t.message_id = gco.message_id
INNER JOIN EXIM1B.ALERT_HEADER AH
ON AH.AT_ID=GCO.WLM_TRANSACTION_ID
INNER JOIN EXIM1B.WORKFLOW_STATUSES WS
ON AH.WW_STATUS_CODE =WS.CODE
WHERE GCO.MESSAGE_ID =:1
AND GCO.IDENTIFICATOR_ID = t.minval
) =
(SELECT COUNT(*)
FROM EXIM1B.GER_CUSTOMER_ONBOARDING GCO inner join t on t.message_id = gco.message_id
INNER JOIN EXIM1B.ALERT_HEADER AH
ON AH.AT_ID=GCO.WLM_TRANSACTION_ID
INNER JOIN EXIM1B.WORKFLOW_STATUSES WS
ON AH.WW_STATUS_CODE =WS.CODE
AND WS.CODE ='S_WLM_WL_013'
WHERE GCO.MESSAGE_ID =:1
AND GCO.IDENTIFICATOR_ID = t.minval
)
THEN 'OK'
ELSE null END AS StatusAlert FROM DUAL
解决方法
您可以减少在同一查询中计算过滤状态和未过滤状态的成本:
SELECT CASE WHEN COUNT(*) = SUM(CASE WHEN WS.CODE='S_WLM_WL_013' THEN 1 ELSE 0 END) THEN 'OK' ELSE NULL END AS StatusAlert
FROM EXIM1B.GER_CUSTOMER_ONBOARDING GCO
INNER JOIN EXIM1B.ALERT_HEADER AH ON AH.AT_ID = GCO.WLM_TRANSACTION_ID
INNER JOIN EXIM1B.WORKFLOW_STATUSES WS ON AH.WW_STATUS_CODE = WS.CODE
WHERE GCO.MESSAGE_ID = :1
AND GCO.IDENTIFICATOR_ID = (
SELECT MIN(IDENTIFICATOR_ID)
FROM EXIM1B.GER_CUSTOMER_ONBOARDING
WHERE MESSAGE_ID = :1
)
FROM DUAL
编辑
您可以进一步降低查询成本,但不包括JOIN
表上的WORKFLOW_STATUSES
并直接过滤EXIM1B.ALERT_HEADER.WW_STATUS_CODE
SELECT CASE WHEN COUNT(*) = SUM(CASE WHEN /* WS.CODE */WW_STATUS_CODE='S_WLM_WL_013' THEN 1 ELSE 0 END) THEN 'OK' ELSE NULL END AS StatusAlert
FROM EXIM1B.GER_CUSTOMER_ONBOARDING GCO
INNER JOIN EXIM1B.ALERT_HEADER AH ON AH.AT_ID = GCO.WLM_TRANSACTION_ID
/* EXIM1B.WORKFLOW_STATUSES NOT NEEDED */
/* INNER JOIN EXIM1B.WORKFLOW_STATUSES WS ON AH.WW_STATUS_CODE = WS.CODE */
WHERE GCO.MESSAGE_ID = :1
AND GCO.IDENTIFICATOR_ID = (
SELECT MIN(IDENTIFICATOR_ID)
FROM EXIM1B.GER_CUSTOMER_ONBOARDING
WHERE MESSAGE_ID = :1
)
FROM DUAL
,
您可以在下面尝试
WITH customer_onboarding
AS
(SELECT /*+ materialize */
gco.wlm_transaction_id
FROM exim1b.ger_customer_onboarding gco
WHERE gco.message_id = :1
AND gco.identificator_id = (SELECT MIN(identificator_id)
FROM exim1b.ger_customer_onboarding
WHERE message_id = :1)),wrk_flw_not_filtered
AS
(SELECT /*+ materialize */
ws.code,count(*) over () as cnt_not_filtered
FROM customer_onboarding gco
JOIN exim1b.alert_header ah
ON ah.at_id = gco.wlm_transaction_id
JOIN exim1b.workflow_statuses ws
ON ah.ww_status_code = ws.code)
SELECT CASE
WHEN max(cnt_not_filtered) = count(*)
THEN 'OK'
END statusalert
FROM wrk_flw_not_filtered flt
WHERE flt.code = 'S_WLM_WL_013';
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。