如何改进以下具有自联接的SQL

时间:2013-04-03 18:09:26

标签: sql oracle sqlperformance

执行选择后,我正在进行自我连接并对数据进行区分。我不确定是否有更好的方法来编写此查询。你能建议吗?

以下是查询和解释计划输出。

   WITH data
        AS (  SELECT san.S1FK_C_ID,
                     san.S1FK_CF_ID,
                     san.S1FK_A_ID,
                     san.S1FK_A_TYPE,
                     san.S1FK_S_TYPE,
                     san.S1FK_B_FUNC,
                     AU.AS1FK_A_ID,
                     AU.AS1FK_B_FUNC,
                     AU.AS1FK_S_TYPE,
                     AU.AS1FK_T_CODE,
                     A2FK_B_ID,
                     A2FK_NBR,
                     A2FK_C_CD,
                     A1FK_B_ID,
                     A1FK_NBR,
                     A1FK_C_CD,
                     AU.R_NAME,
                     IND
                FROM N_RULE cnr,
                     SAN san,
                     ACCT_USG AU
               WHERE     AU.R_NAME = CNR.R_NAME
                     AND AU.A2FK_C_CD = CNR.C_CD
                     AND AU.AS1FK_B_FUNC = CNR.B_FUNC
                     AND AU.AS1FK_A_ID = san.AS1FK_ID || ''
                     AND AU.AS1FK_B_FUNC = san.AS1FK_B_FUNC
                     AND AU.AS1FK_S_TYPE = san.AS1FK_S_TYPE
                     AND AU.AS1FK_T_CODE = san.AS1FK_A_TYPE
                     AND CNR.FM_CODE = 'SP'
                     AND san.STATUS = 'A'
                     AND san.AS1FK_B_FUNC = CNR.B_FUNC
            ORDER BY AU.AS1FK_A_ID)
   SELECT DISTINCT A.A2FK_C_CD AS C_CD,
                   -- secondary id's
                   B.S1FK_C_ID AS C_ID_2,
                   B.S1FK_CF_ID AS CF_ID_2,
                   B.S1FK_A_ID AS A_ID_2,
                   B.S1FK_B_FUNC AS B_FUNC_2,
                   B.S1FK_S_TYPE AS S_TYPE_2,
                   B.S1FK_A_TYPE AS A_TYPE_2,
                   --primary id's
                   A.S1FK_A_ID AS A_ID_1,
                   A.S1FK_B_FUNC AS B_FUNC_1,
                   A.S1FK_S_TYPE AS S_TYPE_1,
                   A.S1FK_A_TYPE AS A_TYPE_1
     FROM data A,            --A is the set of primary and standalone id's
                 data B
    --B is the primary and secondary id's
    WHERE                  
         B    .R_NAME = A.R_NAME
          --as join
          AND B.AS1FK_B_FUNC = A.AS1FK_B_FUNC
          AND B.AS1FK_S_TYPE = A.AS1FK_S_TYPE
          AND B.AS1FK_T_CODE = A.AS1FK_T_CODE
          --accts join
          AND B.A2FK_NBR = A.A2FK_NBR
          AND B.A2FK_B_ID = A.A2FK_B_ID
          AND B.A2FK_C_CD = A.A2FK_C_CD
          AND B.A1FK_NBR = A.A1FK_NBR
          AND B.A1FK_B_ID = A.A1FK_B_ID
          AND B.A1FK_C_CD = A.A1FK_C_CD
          --s fk join
          AND B.S1FK_C_ID = A.S1FK_C_ID
          AND B.S1FK_CF_ID = A.S1FK_CF_ID
          AND B.S1FK_S_TYPE = A.S1FK_S_TYPE
          AND B.S1FK_B_FUNC = A.S1FK_B_FUNC
          AND B.S1FK_A_TYPE = A.S1FK_A_TYPE
          AND (      --join secondary ( N )  and primary id's ( Y ) to primary id's
               ( 'Y'     = A.IND
                  AND B.IND IN ('N', 'Y') )
               OR                     --join standalone ( ' ' ) id's to themselves
                  ( ' '   = B.IND
                  AND ' ' = A.IND )
                  AND B.AS1FK_A_ID = A.AS1FK_A_ID
                  );

安排:

PLAN_TABLE_OUTPUT
Plan hash value: 3120521488

----------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |                             |     1 |   450 |    18  (17)| 00:00:01 |
|   1 |  TEMP TABLE TRANSFORMATION       |                             |       |       |            |          |
|   2 |   LOAD AS SELECT                 | SYS_TEMP_0FD9D949F_E879D9BC |       |       |            |          |
|   3 |    SORT ORDER BY                 |                             |     1 |   296 |    12   (9)| 00:00:01 |
|   4 |     NESTED LOOPS                 |                             |     1 |   296 |    11   (0)| 00:00:01 |
|   5 |      NESTED LOOPS                |                             |  7412 |  1889K|    11   (0)| 00:00:01 |
|*  6 |       TABLE ACCESS FULL          | SAN                         |   255 | 20910 |    11   (0)| 00:00:01 |
|   7 |       TABLE ACCESS BY INDEX ROWID| ACCT_USG                    |    29 |  5191 |     0   (0)| 00:00:01 |
|*  8 |        INDEX RANGE SCAN          | ACCT_USG_PK                 |     1 |       |     0   (0)| 00:00:01 |
|*  9 |      INDEX UNIQUE SCAN           | N_RULE_PK                   |     1 |    35 |     0   (0)| 00:00:01 |
|  10 |   HASH UNIQUE                    |                             |     1 |   450 |     6  (34)| 00:00:01 |
|* 11 |    HASH JOIN                     |                             |     1 |   450 |     5  (20)| 00:00:01 |
|  12 |     VIEW                         |                             |     1 |   225 |     2   (0)| 00:00:01 |
|  13 |      TABLE ACCESS FULL           | SYS_TEMP_0FD9D949F_E879D9BC |     1 |   225 |     2   (0)| 00:00:01 |
|  14 |     VIEW                         |                             |     1 |   225 |     2   (0)| 00:00:01 |
|  15 |      TABLE ACCESS FULL           | SYS_TEMP_0FD9D949F_E879D9BC |     1 |   225 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   6 - filter("SAN"."EFF_STATUS_CODE"='A')
   8 - access("AU"."AS1FK_A_ID"="SAN"."AS1FK_ID"||'' AND 
              "AU"."AS1FK_T_CODE"="SAN"."AS1FK_A_TYPE" AND 
              "AU"."AS1FK_S_TYPE"="SAN"."AS1FK_S_TYPE" AND 
              "AU"."AS1FK_B_FUNC"="SAN"."AS1FK_B_FUNC")
   9 - access("CNR"."FM_CODE"='SP' AND "SAN"."S1FK_C_ID"="CNR"."CLRG_ORG_ID" AND 
              "SAN"."AS1FK_B_FUNC"="CNR"."B_F_CODE" AND "AU"."A2FK_C_CD"="CNR"."C_CD" AND 
              "AU"."R_NAME"="CNR"."R_NAME")
       filter("AU"."AS1FK_B_FUNC"="CNR"."B_F_CODE")
  11 - access("B"."R_NAME"="A"."R_NAME" AND "B"."AS1FK_B_FUNC"="A"."AS1FK_B_FUNC" AND 
              "B"."AS1FK_S_TYPE"="A"."AS1FK_S_TYPE" AND "B"."AS1FK_T_CODE"="A"."AS1FK_T_CODE" 
              AND "B"."A2FK_NBR"="A"."A2FK_NBR" AND "B"."A2FK_B_ID"="A"."A2FK_B_ID" AND 
              "B"."A2FK_C_CD"="A"."A2FK_C_CD" AND "B"."A1FK_NBR"="A"."A1FK_NBR" AND 
              "B"."A1FK_B_ID"="A"."A1FK_B_ID" AND "B"."A1FK_C_CD"="A"."A1FK_C_CD" AND 
              "B"."S1FK_C_ID"="A"."S1FK_C_ID" AND "B"."S1FK_CF_ID"="A"."S1FK_CF_ID" AND 
              "B"."S1FK_S_TYPE"="A"."S1FK_S_TYPE" AND "B"."S1FK_B_FUNC"="A"."S1FK_B_FUNC" AND 
              "B"."STACO1FK_A_TYPE"="A"."STACO1FK_A_TYPE")
       filter("A"."IND"='Y' AND ("B"."IND"='N' OR 
              "B"."IND"="A"."IND") OR "B"."IND"=' ' AND 
              "A"."IND"=' ' AND "B"."AS1FK_A_ID"="A"."AS1FK_A_ID" AND 
              "B"."IND"="A"."IND")


EDIT
~~~~
  1. 我编辑了上面的SQL来删除自联接和不必要的分组。
  2. 我只根据join在primary_secondary行上进行分组。
  3. 在主要和次要之间,我决定应插入次要的主要帐户。
  4. 这给出了相同的结果。我想知道这是否可以进一步改进。

    WITH data
           AS (  SELECT sanw.STAC01FK_C_ID,
                        sanw.STAC01FK_CF_ID,
                        sanw.STAC01FK_A_ID,
                        sanw.STACO1FK_A_TYPE,
                        sanw.STAC01FK_S_TYPE,
                        sanw.STAC01FK_B_FUNC,
                        BAU.ASAC01FK_A_ID,
                        BAU.ASAC01FK_B_FUNC,
                        BAU.ASAC01FK_S_TYPE,
                        BAU.ASAC01FK_TYPE_CODE,
                        BAAC02FK_BANK_ID,
                        BAAC02FK_NBR,
                        BAAC02FK_CURR_CD,
                        BAAC01FK_BANK_ID,
                        BAAC01FK_NBR,
                        BAAC01FK_CURR_CD,
                        BAU.R_NAME,
                        PRIMARY_ACCT_IND
                   FROM N_RULE cnr,
                        SAN sanw,
                        ACCT_USG bau
                  WHERE     BAU.R_NAME = CNR.R_NAME
                        AND BAU.BAAC02FK_CURR_CD = CNR.C_CD
                        AND BAU.ASAC01FK_B_FUNC = CNR.B_FUNC_CD
                        AND BAU.ASAC01FK_A_ID = sanw.ASAC01FK_ID
                        AND BAU.ASAC01FK_B_FUNC = sanw.ASAC01FK_B_FUNC
                        AND BAU.ASAC01FK_S_TYPE = sanw.ASAC01FK_S_TYPE
                        AND BAU.ASAC01FK_TYPE_CODE = sanw.ASAC01FK_A_TYPE
                        AND CNR.FM_CODE = 'SP'
                        AND sanw.EFF_STATUS_CODE = 'A'
                        AND sanw.ASAC01FK_B_FUNC = CNR.B_FUNC_CD),
           primary_secondary
           AS (SELECT PRIMARY_ACCT_IND,
                      B.BAAC02FK_CURR_CD AS C_CD,
                      B.STAC01FK_C_ID AS C_ID_2,
                      B.STAC01FK_CF_ID AS CF_ID_2,
                      -- secondary accounts
                      B.STAC01FK_A_ID AS A_ID_2,
                      B.STAC01FK_B_FUNC AS B_FUNC_2,
                      B.STAC01FK_S_TYPE AS S_TYPE_2,
                      B.STACO1FK_A_TYPE AS A_TYPE_2,
                      --primary accounts
                      B.STAC01FK_A_ID AS A_ID_1,
                      B.STAC01FK_B_FUNC AS B_FUNC_1,
                      B.STAC01FK_S_TYPE AS S_TYPE_1,
                      B.STACO1FK_A_TYPE AS A_TYPE_1,
                      RANK ()
                      OVER (
                         PARTITION BY 
                                      --bank acct join
                                      B.BAAC02FK_CURR_CD,
                                      --sa join
                                      B.STAC01FK_S_TYPE,
                                      B.STAC01FK_B_FUNC,
                                      B.STACO1FK_A_TYPE,
                                      B.STAC01FK_C_ID,
                                      B.STAC01FK_CF_ID
                         ORDER BY
                                      PRIMARY_ACCT_IND DESC)
                         AS d_rank
                 FROM data B
                WHERE B.PRIMARY_ACCT_IND IN ('Y', 'N')),
           stand_alone
           AS (SELECT          B.BAAC02FK_CURR_CD AS C_CD,
                               B.STAC01FK_C_ID AS C_ID_2,
                               B.STAC01FK_CF_ID AS CF_ID_2,
                               -- secondary accounts
                               B.STAC01FK_A_ID AS A_ID_2,
                               B.STAC01FK_B_FUNC AS B_FUNC_2,
                               B.STAC01FK_S_TYPE AS S_TYPE_2,
                               B.STACO1FK_A_TYPE AS A_TYPE_2,
                               --primary accounts
                               B.STAC01FK_A_ID AS A_ID_1,
                               B.STAC01FK_B_FUNC AS B_FUNC_1,
                               B.STAC01FK_S_TYPE AS S_TYPE_1,
                               B.STACO1FK_A_TYPE AS A_TYPE_1
                 FROM data B
                WHERE B.PRIMARY_ACCT_IND = ' '),
           PRIMARY
           AS (SELECT C_CD,
                      C_ID_2,
                      CF_ID_2,
                      -- secondary accounts
                      A_ID_2,
                      B_FUNC_2,
                      S_TYPE_2,
                      A_TYPE_2,
                      --primary accounts
                      A_ID_1,
                      B_FUNC_1,
                      S_TYPE_1,
                      A_TYPE_1
                 FROM primary_secondary
                WHERE D_RANK = 1),
           SECONDARY
           AS (SELECT ps.C_CD,
                      ps.C_ID_2,
                      ps.CF_ID_2,
                      -- secondary accounts
                      ps.A_ID_2,
                      ps.B_FUNC_2,
                      ps.S_TYPE_2,
                      ps.A_TYPE_2,
                      --primary accounts
                      p.A_ID_1,
                      p.B_FUNC_1,
                      p.S_TYPE_1,
                      p.A_TYPE_1
                 FROM primary_secondary ps, primary p
                WHERE     ps.D_RANK <> 1
                      AND ps.C_CD = p.C_CD
                      AND ps.C_ID_2 = p.C_ID_2
                      AND ps.CF_ID_2 = p.CF_ID_2
                      --  secondarary accounts
                      AND ps.B_FUNC_2 = p.B_FUNC_2
                      AND ps.S_TYPE_2 = p.S_TYPE_2
                      AND ps.A_TYPE_2 = p.A_TYPE_2)
      SELECT * FROM secondary
      UNION ALL
      SELECT * FROM primary
      UNION ALL
      SELECT * FROM stand_alone
    

    计划:

    Plan hash value: 3159296610
    
    ----------------------------------------------------------------------------------------------------------
    | Id  | Operation                  | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT           |                             |    33 |  3421 |     9  (56)| 00:00:01 |
    |   1 |  TEMP TABLE TRANSFORMATION |                             |       |       |            |          |
    |   2 |   LOAD AS SELECT           | SYS_TEMP_0FD9DBAF1_9261CF31 |       |       |            |          |
    |*  3 |    HASH JOIN               |                             |    11 |  3058 |   119   (1)| 00:00:02 |
    |*  4 |     HASH JOIN              |                             |    96 | 18816 |   104   (1)| 00:00:02 |
    |*  5 |      INDEX RANGE SCAN      | CNR_PK                  |    61 |  1769 |     1   (0)| 00:00:01 |
    |   6 |      TABLE ACCESS FULL     | ACCT_USG                |  8244 |  1344K|   102   (0)| 00:00:02 |
    |*  7 |     TABLE ACCESS FULL      | SAN                     |  1444 |   115K|    15   (0)| 00:00:01 |
    |   8 |   LOAD AS SELECT           | SYS_TEMP_0FD9DBAF2_9261CF31 |       |       |            |          |
    |   9 |    WINDOW SORT             |                             |    11 |   594 |     3  (34)| 00:00:01 |
    |* 10 |     VIEW                   |                             |    11 |   594 |     2   (0)| 00:00:01 |
    |  11 |      TABLE ACCESS FULL     | SYS_TEMP_0FD9DBAF1_9261CF31 |    11 |  2343 |     2   (0)| 00:00:01 |
    |  12 |   LOAD AS SELECT           | SYS_TEMP_0FD9DBAF3_9261CF31 |       |       |            |          |
    |* 13 |    VIEW                    |                             |    11 |  1089 |     2   (0)| 00:00:01 |
    |  14 |     TABLE ACCESS FULL      | SYS_TEMP_0FD9DBAF2_9261CF31 |    11 |   682 |     2   (0)| 00:00:01 |
    |  15 |   UNION-ALL                |                             |       |       |            |          |
    |* 16 |    HASH JOIN               |                             |    11 |  1672 |     5  (20)| 00:00:01 |
    |* 17 |     VIEW                   |                             |    11 |   792 |     2   (0)| 00:00:01 |
    |  18 |      TABLE ACCESS FULL     | SYS_TEMP_0FD9DBAF2_9261CF31 |    11 |   682 |     2   (0)| 00:00:01 |
    |  19 |     VIEW                   |                             |    11 |   880 |     2   (0)| 00:00:01 |
    |  20 |      TABLE ACCESS FULL     | SYS_TEMP_0FD9DBAF3_9261CF31 |    11 |   946 |     2   (0)| 00:00:01 |
    |  21 |    VIEW                    |                             |    11 |  1067 |     2   (0)| 00:00:01 |
    |  22 |     TABLE ACCESS FULL      | SYS_TEMP_0FD9DBAF3_9261CF31 |    11 |   946 |     2   (0)| 00:00:01 |
    |* 23 |    VIEW                    |                             |    11 |   682 |     2   (0)| 00:00:01 |
    |  24 |     TABLE ACCESS FULL      | SYS_TEMP_0FD9DBAF1_9261CF31 |    11 |  2343 |     2   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       3 - access("BAU"."ASAC01FK_A_ID"="SANW"."ASAC01FK_ID"||'' AND 
                  "BAU"."ASAC01FK_B_FUNC"="SANW"."ASAC01FK_B_FUNC" AND 
                  "BAU"."ASAC01FK_S_TYPE"="SANW"."ASAC01FK_S_TYPE" AND 
                  "BAU"."ASAC01FK_TYPE_CODE"="SANW"."ASAC01FK_A_TYPE" AND 
                  "SANW"."ASAC01FK_B_FUNC"="CNR"."B_FUNC_CD")
       4 - access("BAU"."R_NAME"="CNR"."R_NAME" AND 
                  "BAU"."BAAC02FK_CURR_CD"="CNR"."C_CD" AND 
                  "BAU"."ASAC01FK_B_FUNC"="CNR"."B_FUNC_CD")
       5 - access("CNR"."FM_CODE"='SP')
       7 - filter("SANW"."EFF_STATUS_CODE"='A')
      10 - filter("B"."PRIMARY_ACCT_IND"='N' OR "B"."PRIMARY_ACCT_IND"='Y')
      13 - filter("D_RANK"=1)
      16 - access("PS"."C_CD"="P"."C_CD" AND "PS"."C_ID_2"="P"."C_ID_2" AND 
                  "PS"."CF_ID_2"="P"."CF_ID_2" AND "PS"."B_FUNC_2"="P"."B_FUNC_2" AND 
                  "PS"."S_TYPE_2"="P"."S_TYPE_2" AND "PS"."A_TYPE_2"="P"."A_TYPE_2")
      17 - filter("PS"."D_RANK"<>1)
      23 - filter("B"."PRIMARY_ACCT_IND"=' ')
    

0 个答案:

没有答案