当我执行我的代码时,它花费了很多小时并且还没有完成。我知道问题是在左连接子句中使用“or”。所以我想知道如何重写这段可以执行的代码。
SELECT WFTD.RELA
, WFTCS.PARENT_TASK AS CONSULT_TASK_ID
, WFTCS.CREATE_DATE AS CONSULT_DATE
, WFTD_THIS_TASK.APPROVED_RESULT_DATE AS THISTASK_APPROVED_RESULT_DATE
FROM TNH_WF WF
INNER JOIN TND_WF_TASK WFT ON WFT.WF_ID = WF.WF_ID AND WFT.OWNER_ATONEMENT IS NOT NULL AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06', 'N07')
INNER JOIN TND_WF_TASK WFTCS ON WFTCS.WF_ID = WFT.WF_ID AND WFTCS.WORK_TRAY_ID = 'N07'
LEFT JOIN TND_WF_TASK_DETAIL WFTD_THIS_TASK ON WFTD_THIS_TASK.WF_TASK_ID = WFT.WF_TASK_ID AND WFTD_THIS_TASK.POL_COV_FLAG = 'P'
LEFT JOIN TND_WF_TASK_DETAIL WFTD
ON (
(
(WFTD.WF_TASK_ID = WFT.PARENT_TASK
AND WFT.WORK_TRAY_ID IN ('N07')
AND WFTD.CONSIDER_RESULT_CODE LIKE '%Consult%')
OR
(WFTD.NEXT_TASK_ID = WFT.WF_TASK_ID
AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06'))
AND
WFT.STATUS IN (0,1,2)
)
OR
(WFTD.WF_TASK_ID = WFT.WF_TASK_ID
AND WFT.STATUS IN (3)))
AND WFTD.POL_COV_FLAG = 'P'
in this optimized query i did following things:
1. I've separated the JOIN conditions into separate LEFT JOIN clauses
to improve readability.
2. I've simplified the WHERE clause by using an explicit check for
WFTD.WF_TASK_ID IS NOT NULL OR WFT.STATUS = 3 instead of the complex
condition in the original query.
3. Make sure proper indexing is in place for the join columns and the
columns used in WHERE conditions for optimal performance.
SELECT
WFTD.RELA,
WFTCS.PARENT_TASK AS CONSULT_TASK_ID,
WFTCS.CREATE_DATE AS CONSULT_DATE,
WFTD_THIS_TASK.APPROVED_RESULT_DATE AS THISTASK_APPROVED_RESULT_DATE
FROM
TNH_WF WF
INNER JOIN
TND_WF_TASK WFT ON WFT.WF_ID = WF.WF_ID
AND WFT.OWNER_ATONEMENT IS NOT NULL
AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06', 'N07')
INNER JOIN
TND_WF_TASK WFTCS ON WFTCS.WF_ID = WFT.WF_ID
AND WFTCS.WORK_TRAY_ID = 'N07'
LEFT JOIN
TND_WF_TASK_DETAIL WFTD_THIS_TASK ON WFTD_THIS_TASK.WF_TASK_ID = WFT.WF_TASK_ID
AND WFTD_THIS_TASK.POL_COV_FLAG = 'P'
LEFT JOIN
TND_WF_TASK_DETAIL WFTD ON WFTD.WF_TASK_ID = WFT.PARENT_TASK
AND WFT.WORK_TRAY_ID IN ('N07')
AND WFTD.CONSIDER_RESULT_CODE LIKE '%Consult%'
AND WFT.STATUS IN (0, 1, 2)
AND WFTD.POL_COV_FLAG = 'P'
LEFT JOIN
TND_WF_TASK_DETAIL WFTD_NEXT ON WFTD_NEXT.NEXT_TASK_ID = WFT.WF_TASK_ID
AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06')
AND WFT.STATUS IN (0, 1, 2)
AND WFTD_NEXT.POL_COV_FLAG = 'P'
WHERE
(WFTD.WF_TASK_ID IS NOT NULL OR WFT.STATUS = 3)
虽然我们在没有看到您的执行数据的情况下无法确定,但这很可能是由于您加入了
WFTD
,正如您所猜对的那样。有多种方法可以解决这个问题。从最少的重写到最大的重写:
向查询块添加
/*+ USE_CONCAT */
提示(位于顶部 SELECT
关键字之后)。这可能会促使 Oracle 将您的查询重写为一系列 UNION
(或 UNION ALL
后跟 DISTINCT
排序)块,每个块都有明确的等值连接条件以消除 OR
条件。但由于您还有一些复合和 IN
运算符,Oracle 可能会遇到困难。值得一试,因为除了提示之外不需要更改代码。
如果到
WFTD
的连接是1:1连接(WFTD
中最多只有一行可能匹配任何可能的连接条件),您可以简单地连接到表3次并然后从找到的结果中取出您需要的列:
SELECT COALESCE(WFTD1.RELA,WFTD2.RELA,WFTD3.RELA) AS RELA
, WFTCS.PARENT_TASK AS CONSULT_TASK_ID
, WFTCS.CREATE_DATE AS CONSULT_DATE
, WFTD_THIS_TASK.APPROVED_RESULT_DATE AS THISTASK_APPROVED_RESULT_DATE
FROM TNH_WF WF
INNER JOIN TND_WF_TASK WFT ON WFT.WF_ID = WF.WF_ID AND WFT.OWNER_ATONEMENT IS NOT NULL AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06', 'N07')
INNER JOIN TND_WF_TASK WFTCS ON WFTCS.WF_ID = WFT.WF_ID AND WFTCS.WORK_TRAY_ID = 'N07'
LEFT JOIN TND_WF_TASK_DETAIL WFTD_THIS_TASK ON WFTD_THIS_TASK.WF_TASK_ID = WFT.WF_TASK_ID AND WFTD_THIS_TASK.POL_COV_FLAG = 'P'
LEFT JOIN TND_WF_TASK_DETAIL WFTD1 ON WFTD1.WF_TASK_ID = WFT.PARENT_TASK
AND WFTD1.CONSIDER_RESULT_CODE LIKE '%Consult%'
AND WFT.WORK_TRAY_ID IN ('N07')
AND WFT.STATUS IN (0,1,2)
AND WFTD1.POL_COV_FLAG = 'P'
LEFT JOIN TND_WF_TASK_DETAIL WFTD2 ON WFTD2.NEXT_TASK_ID = WFT.WF_TASK_ID
AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06')
AND WFT.STATUS IN (0,1,2)
AND WFTD2.POL_COV_FLAG = 'P'
LEFT JOIN TND_WF_TASK_DETAIL WFTD3 ON WFTD3.WF_TASK_ID = WFT.WF_TASK_ID
AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06')
AND WFT.STATUS IN (3)
AND WFTD3.POL_COV_FLAG = 'P'
最后,如果 Oracle 无法通过提示为您重写它,并且与 WFTD 的连接可能not 为 1:1(这可能导致上面选项 #2 中的行扩展 [行数过多]),那么您可以使用
UNION
重写整个查询。将其复制粘贴三次,并用 UNION
连接,将连接折叠为每个连接中的三个连接之一:
SELECT WFTD.RELA
, WFTCS.PARENT_TASK AS CONSULT_TASK_ID
, WFTCS.CREATE_DATE AS CONSULT_DATE
, WFTD_THIS_TASK.APPROVED_RESULT_DATE AS THISTASK_APPROVED_RESULT_DATE
FROM TNH_WF WF
INNER JOIN TND_WF_TASK WFT ON WFT.WF_ID = WF.WF_ID AND WFT.OWNER_ATONEMENT IS NOT NULL AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06', 'N07')
INNER JOIN TND_WF_TASK WFTCS ON WFTCS.WF_ID = WFT.WF_ID AND WFTCS.WORK_TRAY_ID = 'N07'
LEFT JOIN TND_WF_TASK_DETAIL WFTD_THIS_TASK ON WFTD_THIS_TASK.WF_TASK_ID = WFT.WF_TASK_ID AND WFTD_THIS_TASK.POL_COV_FLAG = 'P'
LEFT JOIN TND_WF_TASK_DETAIL WFTD ON WFTD.WF_TASK_ID = WFT.PARENT_TASK
AND WFTD.CONSIDER_RESULT_CODE LIKE '%Consult%'
AND WFT.WORK_TRAY_ID IN ('N07')
AND WFT.STATUS IN (0,1,2)
AND WFTD.POL_COV_FLAG = 'P'
UNION
SELECT WFTD.RELA
, WFTCS.PARENT_TASK AS CONSULT_TASK_ID
, WFTCS.CREATE_DATE AS CONSULT_DATE
, WFTD_THIS_TASK.APPROVED_RESULT_DATE AS THISTASK_APPROVED_RESULT_DATE
FROM TNH_WF WF
INNER JOIN TND_WF_TASK WFT ON WFT.WF_ID = WF.WF_ID AND WFT.OWNER_ATONEMENT IS NOT NULL AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06', 'N07')
INNER JOIN TND_WF_TASK WFTCS ON WFTCS.WF_ID = WFT.WF_ID AND WFTCS.WORK_TRAY_ID = 'N07'
LEFT JOIN TND_WF_TASK_DETAIL WFTD_THIS_TASK ON WFTD_THIS_TASK.WF_TASK_ID = WFT.WF_TASK_ID AND WFTD_THIS_TASK.POL_COV_FLAG = 'P'
LEFT JOIN TND_WF_TASK_DETAIL WFTD ON WFTD.NEXT_TASK_ID = WFT.WF_TASK_ID
AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06')
AND WFT.STATUS IN (0,1,2)
AND WFTD.POL_COV_FLAG = 'P'
UNION
SELECT WFTD.RELA
, WFTCS.PARENT_TASK AS CONSULT_TASK_ID
, WFTCS.CREATE_DATE AS CONSULT_DATE
, WFTD_THIS_TASK.APPROVED_RESULT_DATE AS THISTASK_APPROVED_RESULT_DATE
FROM TNH_WF WF
INNER JOIN TND_WF_TASK WFT ON WFT.WF_ID = WF.WF_ID AND WFT.OWNER_ATONEMENT IS NOT NULL AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06', 'N07')
INNER JOIN TND_WF_TASK WFTCS ON WFTCS.WF_ID = WFT.WF_ID AND WFTCS.WORK_TRAY_ID = 'N07'
LEFT JOIN TND_WF_TASK_DETAIL WFTD_THIS_TASK ON WFTD_THIS_TASK.WF_TASK_ID = WFT.WF_TASK_ID AND WFTD_THIS_TASK.POL_COV_FLAG = 'P'
LEFT JOIN TND_WF_TASK_DETAIL WFTD ON WFTD.WF_TASK_ID = WFT.WF_TASK_ID
AND WFT.WORK_TRAY_ID IN ('N02', 'N03', 'N06')
AND WFT.STATUS IN (3)
AND WFTD.POL_COV_FLAG = 'P'