微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何重写此Oracle查询以使用有效的CTE

如何解决如何重写此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 举报,一经查实,本站将立刻删除。