1

我目前正在尝试改进用于构建视图的查询。查询在 PL/SQL 中,在 Oracle 数据库中。每个建筑物都会生成 3 种不同类型的报告(100,200 和 300)。我们跟踪生成每份报告的连续年份,并根据 (1) 给定年份生成的报告类型和 (2) 每份报告生成的连续年份的组合,我们得出在该建筑物的结果类型处。

以下是结果类型标准的描述:

结果 600 - 如果所有 3 种报告类型均在当年生成,其中: 级别 1:所有报告均连续 1 年生成(这是第一年) 级别 2:至少连续 2 年生成 1 种报告类型年(无连续 3 年) 3 级:至少连续 3 年生成一种报告类型

结果 100 - 本年度仅生成报告类型 100,其中: 级别 1 - 连续 1 年 级别 2 - 连续 2 年 级别 3 - 连续 3 年

结果 200 - 本年度仅生成报告类型 200,其中: 级别 1 - 连续 1 年 级别 2 - 连续 2 年 级别 3 - 连续 3 年

结果 300 - 本年度仅生成报告类型 300,其中: 1 级 - 连续 1 年 2 级 - 连续 2 年 3 级 - 连续 3 年

结果 400 - 仅生成报告 100 和 200,其中: 级别 1:连续 1 年生成两个报告(这是第一年) 级别 2:连续 2 年至少生成 1 种报告类型(均未生成)连续 3 年)3 级:至少连续 3 年生成一种报告类型

结果 500 - 仅生成报告 100 和 300,其中: 级别 1:连续 1 年生成两个报告(这是第一年) 级别 2:连续 2 年至少生成 1 种报告类型(均未生成)连续 3 年)3 级:至少连续 3 年生成一种报告类型

结果 700 - 仅生成了报告 200 和 300,其中: 级别 1:连续 1 年生成两个报告(这是第一年) 级别 2:至少连续 2 年生成了一种报告类型(两者都没有连续 3 年)3 级:至少连续 3 年生成一种报告类型

还在我这儿?甜的。因此,这里是用于生成此视图的当前代码,它只是结果的显示:

CREATE OR REPLACE FORCE VIEW REPORTS.REPORT_RESULT_VIEW
(
   BUILDING,
   BUILDING_NAME,
   GROUP,
   YEAR,
   TYPE,
   SUBTYPE,
   CONSEC,
   RESULT
)
AS
   WITH cte1
        AS (SELECT 1 ID_100,
                   1 ID_200,
                   1 ID_300,
                   '600 Level 1' RESULT
              FROM DUAL
            UNION ALL
            SELECT 2 ID_100,
                   2 ID_200,
                   2 ID_300,
                   '600 Level 2' RESULT
              FROM DUAL
            UNION ALL
            SELECT 3 ID_100,
                   3 ID_200,
                   3 ID_300,
                   '600 Level 3' RESULT
              FROM DUAL
            UNION ALL
            SELECT 1 ID_100,
                   1 ID_200,
                   2 ID_300,
                   '600 Level 2' RESULT
              FROM DUAL),

(注意 - 实际代码中总共列出了 63 种组合......我只输入了前几个,让您了解它是如何设置的)

        cte2
        AS (  SELECT MAX (ID_100) ID_100_CONSEC,
                     MAX (ID_200) ID_200_CONSEC,
                     MAX (ID_300) ID_300_CONSEC,
                     YEAR,
                     BUILDING
                FROM (SELECT CONSEC ID_100,
                             NULL ID_200,
                             NULL ID_300,
                             YEAR,
                             TYPE || SUBTYPE TYPE,
                             BUILDING
                        FROM REPORT_MASTER_VIEW
                       WHERE TYPE || SUBTYPE = '100'
                      UNION
                      SELECT NULL ID_100,
                             CONSEC ID_200,
                             NULL ID_300,
                             YEAR,
                             TYPE || SUBTYPE TYPE,
                             BUILDING
                        FROM REPORT_MASTER_VIEW
                       WHERE TYPE || SUBTYPE = '200'
                      UNION
                      SELECT NULL ID_100,
                             NULL ID_200,
                             CONSEC ID_300,
                             YEAR,
                             TYPE || SUBTYPE TYPE,
                             BUILDING
                        FROM REPORT_MASTER_VIEW
                       WHERE TYPE || SUBTYPE = '300')
            GROUP BY YEAR, BUILDING),
        cte3
        AS (SELECT c2.*, c1.RESULT
              FROM    cte2 c2
                   JOIN
                      cte1 c1
                   ON     NVL (c2.ID_100_CONSEC, 0) = c1.ID_100
                      AND NVL (c2.ID_200_CONSEC, 0) = c1.ID_200
                      AND NVL (c2.ID_300_CONSEC, 0) = c1.ID_300)
     SELECT t1."BUILDING",
            t1."BUILDING_NAME",
            t1."GROUP",
            t1."YEAR",
            t1."TYPE",
            t1."SUBTYPE",
            t1."CONSEC",
            t2.RESULT
       FROM    REPORT_MASTER_VIEW t1
            JOIN
               cte3 t2
            ON t1.BUILDING  = t2.BUILDING AND t1.YEAR = t2.YEAR
      WHERE T1.TYPE IN ('100', '200' '300')
   ORDER BY t1.BUILDING;

现在,因为对于每个报表组合,它都必须遍历所有可能的组合,因此构建此视图大约需要 24 秒。在引用它的应用程序中,加载页面需要将近一分钟。出于这个原因,我试图找出提高查询效率的方法。起初,我在考虑使用嵌套的 CASE 语句,但我并不确定它会如何工作。非常感谢任何有关如何更好地解决此问题的建议。

4

1 回答 1

1
WITH cte2 AS
(
        SELECT  MAX(CASE WHEN TYPE || SUBTYPE = '100' THEN CONSEC END) AS ID_100_CONSEC
        ,       MAX(CASE WHEN TYPE || SUBTYPE = '200' THEN CONSEC END) AS ID_200_CONSEC
        ,       MAX(CASE WHEN TYPE || SUBTYPE = '300' THEN CONSEC END) AS ID_300_CONSEC
        ,       YEAR
        ,       BUILDING
        FROM    REPORT_MASTER_VIEW
        WHERE   TYPE || SUBTYPE IN ('100', '200', '300')
        GROUP   BY
                YEAR
        ,       BUILDING
)
,cte3 AS
(
        SELECT  ID_100_CONSEC
        ,       ID_200_CONSEC
        ,       ID_300_CONSEC
        ,       YEAR
        ,       BUILDING
        ,       CASE
                    WHEN c2.ID_100_CONSEC = 1 THEN '600 Level 1' 
                    WHEN c2.ID_100_CONSEC = 2 THEN '600 Level 2' 
                    WHEN c2.ID_100_CONSEC = 3 THEN '600 Level 3' 
                    WHEN c2.ID_200_CONSEC = 1 THEN '600 Level 1' 
                    WHEN c2.ID_200_CONSEC = 2 THEN '600 Level 2' 
                    WHEN c2.ID_200_CONSEC = 3 THEN '600 Level 3' 
                    WHEN c2.ID_300_CONSEC = 1 THEN '600 Level 1' 
                    WHEN c2.ID_300_CONSEC = 2 THEN '600 Level 2' 
                    WHEN c2.ID_300_CONSEC = 3 THEN '600 Level 3' 
                END AS RESULT
        FROM    cte2
        WHERE   c2.ID_100_CONSEC IN (1, 2, 3)
        OR      c2.ID_200_CONSEC IN (1, 2, 3)
        OR      c2.ID_300_CONSEC IN (1, 2, 3)
)
SELECT  t1."BUILDING",
        t1."BUILDING_NAME",
        t1."GROUP",
        t1."YEAR",
        t1."TYPE",
        t1."SUBTYPE",
        t1."CONSEC",
        t2.RESULT
FROM    REPORT_MASTER_VIEW t1
WHERE   T1.TYPE IN ('100', '200', '300')
AND     EXISTS
        (
            SELECT  1
            FROM    cte3 t2
            WHERE   t1.BUILDING  = t2.BUILDING
            AND     t1.YEAR = t2.YEAR
        )
ORDER   BY
        t1.BUILDING;

Should be pretty close. I think you will need to polish it a little.

于 2013-06-22T03:49:46.123 回答