多个OR EXISTS导致长查询挂起 - 只有一个工作

时间:2016-02-13 00:19:54

标签: sql oracle

尝试让此查询运行。冒号是输入旁边的参数化。

SELECT DISTINCT pa.kas_pa, pa.auth_num FROM t_pa_path pa, t_pa_a_item ai 
WHERE (pa.kas_receipt = :kas_receipt OR 
       pa.ID_receipt_KEYED = :id_receipt_keyed OR 
       pa.kas_receipt IN (SELECT kas_rcp_purged FROM t_receipt_link_xref WHERE kas_receipt = :kas_receipt AND cde_status = 'Z') ) 
AND pa.auth_num <> :auth_num 
AND pa.kas_pa = ai.kas_pa 
AND pa.kas_payer_one = :kas_payer_one 
AND pa.ind_special = :ind_special 
AND pa.ind_emerg = :ind_emerg 
AND pa.the_status IN ('A','B','C','D','E') 
AND pa.kas_prov_loc IN (SELECT kas_prov_loc FROM t_pr_identifier WHERE RTRIM(id_other_cust) = :id_prov_keyed) 
AND :cde_keyed IN (ai.cde_keyed, ai.cde_2_keyed, ai.cde_3_keyed, ai.cde_4_keyed) 
AND ai.cde_keyed IN (' ',:cde_keyed) 
AND ai.cde_2_keyed IN (' ',:cde_keyed) 
AND ai.cde_3_keyed IN (' ',:cde_keyed) 
AND ai.cde_4_keyed IN (' ',:cde_keyed) 
AND ai.the_STATUS IN ('A','C','E','G','W') 
AND ai.kas_proceding = :kas_proceding
OR EXISTS (SELECT 1 FROM t_pa_a_item ai, t_dup_svc ds JOIN t_prog p ON ds.cde_proceding_2=rtrim(p.cde_proc)   
  WHERE ds.cde_tax_1 = :cde_tax_1 
  AND ds.cde_proceding_1 = :cde_proceding_1 
  AND ds.cde_1 = :cde_1 
  AND ds.cde_tax_2 = ai.cde_tax 
  AND p.kas_proceding = ai.kas_proceding 
  AND ds.cde_2 = ai.cde_keyed)
OR EXISTS (SELECT 1 FROM t_pa_a_item ai, t_dup_svc ds JOIN t_prog p ON ds.cde_proceding_1=rtrim(p.cde_proc) 
  WHERE ds.cde_tax_2 = :cde_tax_1 
  AND ds.cde_proceding_2 = :cde_proceding_1 
  AND ds.cde_2 = :cde_1 
  AND ds.cde_tax_1 = ai.cde_tax 
  AND p.kas_proceding = ai.kas_proceding 
  AND ds.cde_1 = ai.cde_keyed) 
  AND (  ai.dte_pa_req_eff = :dte_pa_req_eff OR 
      ((:dte_pa_req_eff BETWEEN ai.DTE_PA_REQ_EFF AND ai.DTE_PA_REQ_END ) OR 
      ( :dte_pa_req_end BETWEEN ai.DTE_PA_REQ_EFF AND ai.DTE_PA_REQ_END ) OR 
      ( :dte_pa_req_eff < ai.DTE_PA_REQ_EFF AND :dte_pa_req_end > ai.DTE_PA_REQ_END ) ));

当我运行整个查询时,它只是挂起。

当我在第一个OR EXISTS之前从头到尾运行查询时,查询有效(没有错误,没有挂起)。

如果我取出第一个OR EXISTS,并将第二个存在,那么整个查询都有效(没有挂起,没有错误)。

所以这个问题似乎与OR EXISTS在一起,或者可能是第一个OR EXISTS。

有任何想法或建议吗?

感谢。

2 个答案:

答案 0 :(得分:1)

子查询:

OR EXISTS (SELECT 1 
     FROM t_pa_a_item ai, t_dup_svc ds 
           JOIN t_prog p ON ds.cde_proceding_2=rtrim(p.cde_proc)   
 WHERE ds.cde_tax_1 = :cde_tax_1 
       AND ds.cde_proceding_1 = :cde_proceding_1 
       AND ds.cde_1 = :cde_1 
       AND ds.cde_tax_2 = ai.cde_tax 
       AND p.kas_proceding = ai.kas_proceding 
       AND ds.cde_2 = ai.cde_keyed)

看起来很奇怪,因为它与查询的其余部分无关。

在存在主义中,你正在使用一个隐藏外部ai的新别名ai(两者都用于同一个表......所以你正在使用表的新“副本”)。因此,子查询仅依赖于其自己的from表和外部参数。这几乎总是错误的。如果这个存在性为真,那么主from部分的所有行都是如此。如果您指的是原始表t_pa_a_item

,也许您应该省略内部ai

这可能是问题吗?

答案 1 :(得分:0)

首先,考虑使用基本上将WHERE子句中的连接键移动到INNER JOIN子句的explicit join over implicit joinOracle 9i引入了ANSI SQL连接。虽然不是效率或性能的贡献者,但它确实有助于提高可读性和可维护性。

其次,考虑在LEFT JOIN子查询上使用OR EXISTS派生表。此外,重新考虑使用OR EXISTS作为子查询返回的原因是可选的,因此是否考虑,并且没有使用任何列。

下面是重写,可能需要您更新相应的密钥:

SELECT DISTINCT pa.kas_pa, pa.auth_num 
FROM t_pa_path pa
INNER JOIN t_pa_a_item ai 
      ON pa.kas_pa = ai.kas_pa     
LEFT JOIN (
  SELECT ai.kas_pa
  FROM t_pa_a_item ai
  INNER JOIN t_dup_svc ds              -- EDIT FOR PROPER JOIN KEYS 
        ON ds.cde_tax_2 = ai.cde_tax 
        AND ds.cde_2 = ai.cde_keyed
  INNER JOIN t_prog p                  -- EDIT FOR PROPER JOIN KEYS 
        ON ds.cde_proceding_2 = rtrim(p.cde_proc) 
        ON p.kas_proceding = ai.kas_proceding 
  WHERE ds.cde_tax_1 = :cde_tax_1 
  AND ds.cde_proceding_1 = :cde_proceding_1 
  AND ds.cde_1 = :cde_1 
  ) as derivedTable1    
ON ai.kas_pa = derivedTable1.kas_pa    -- EDIT FOR PROPER JOIN KEYS 

LEFT JOIN (
  SELECT ai.kas_pa 
  FROM t_pa_a_item ai 
  INNER JOIN t_dup_svc ds              -- EDIT FOR PROPER JOIN KEYS 
        ON ds.cde_tax_1 = ai.cde_tax 
        AND ds.cde_1 = ai.cde_keyed
  INNER JOIN t_prog p                  -- EDIT FOR PROPER JOIN KEYS 
        ON ds.cde_proceding_1=rtrim(p.cde_proc) 
        ON p.kas_proceding = ai.kas_proceding 
  WHERE ds.cde_tax_2 = :cde_tax_1 
  AND ds.cde_proceding_2 = :cde_proceding_1 
  AND ds.cde_2 = :cde_1 
  AND (  ai.dte_pa_req_eff = :dte_pa_req_eff OR 
      ((:dte_pa_req_eff BETWEEN ai.DTE_PA_REQ_EFF AND ai.DTE_PA_REQ_END ) OR 
      ( :dte_pa_req_end BETWEEN ai.DTE_PA_REQ_EFF AND ai.DTE_PA_REQ_END ) OR 
      ( :dte_pa_req_eff < ai.DTE_PA_REQ_EFF AND :dte_pa_req_end > ai.DTE_PA_REQ_END )) )
  ) AS derivedTable2

ON ai.kas_pa = derivedTable2.kas_pa    -- EDIT FOR PROPER JOIN KEYS

WHERE (pa.kas_receipt = :kas_receipt OR 
       pa.ID_receipt_KEYED = :id_receipt_keyed OR 
       pa.kas_receipt IN (SELECT kas_rcp_purged 
                          FROM t_receipt_link_xref 
                          WHERE kas_receipt = :kas_receipt AND cde_status = 'Z')) 
AND pa.auth_num <> :auth_num 
AND pa.kas_payer_one = :kas_payer_one 
AND pa.ind_special = :ind_special 
AND pa.ind_emerg = :ind_emerg 
AND pa.the_status IN ('A','B','C','D','E') 
AND pa.kas_prov_loc IN (SELECT kas_prov_loc 
                        FROM t_pr_identifier 
                        WHERE RTRIM(id_other_cust) = :id_prov_keyed) 
AND :cde_keyed IN (ai.cde_keyed, ai.cde_2_keyed, ai.cde_3_keyed, ai.cde_4_keyed) 
AND ai.cde_keyed IN (' ',:cde_keyed) 
AND ai.cde_2_keyed IN (' ',:cde_keyed) 
AND ai.cde_3_keyed IN (' ',:cde_keyed) 
AND ai.cde_4_keyed IN (' ',:cde_keyed) 
AND ai.the_STATUS IN ('A','C','E','G','W') 
AND ai.kas_proceding = :kas_proceding;