如何在层次结构树中获得子项的累计总和?

时间:2012-06-05 02:11:27

标签: sql oracle

表“salary”的列是att_month,emp_id(指向员工的emp_id),总计。
表“组织”列是ID,IDParent,名称 表“employee”的列是emp_id,emp_name,dep_id(指向组织的ID)。

目标是根据这三个表计算每个部门的摘要,每个月。我想知道是否有人可以提供SQL查询或优化我的查询?

我目前的查询如下:

   select * from (select yy.IDParent, xx.ID, name, sum(heji) total
       from (select CONNECT_BY_ROOT(ID) ID, heji
                  from (select aa.ID,
                           aa.IDParent,
                           aa.name,
                           nvl(sum(HJ), 0) as heji
                          from (select * from organization) aa,
                           (select att_month,
                                   b.dep_id,
                                   sum(total) as HJ
                              from salary a, employee b
                             where b.emp_id = a.emp_id
                               and to_char(att_month, 'yyyy-mm') =
                                   '2012-05'
                             group by att_month, b.dep_id) bb
                     where aa.ID = bb.dep_id(+)
                     group by aa.ID, aa.IDParent, aa.name)
                connect by prior ID = IDParent) xx,
               organization yy
         where xx.ID = yy.ID
         group by yy.IDParent, xx.ID, name)
    connect by prior ID = IDParent
     start with ID = '000';

但是,它太长了,需要进行优化。怎么样?

    CREATE TABLE "EMPLOYEE" 
       (    "ID" NUMBER(5,0), 
        "EMP_ID" VARCHAR2(5) NOT NULL ENABLE, 
        "PASSWORD" VARCHAR2(8) DEFAULT 1, 
        "EMP_NAME" VARCHAR2(30), 
        "DEP_ID" VARCHAR2(5), 
        "LEV" CHAR(1), 
        "SEX" CHAR(1), 
        "CATEGORY" VARCHAR2(20), 
        "EDU" VARCHAR2(8), 
        "BIRTHDAY" DATE, 
        "GN" DATE, 
        "RJ" DATE, 
        "PID" VARCHAR2(18), 
        "LTY" CHAR(1), 
        "GWMC" VARCHAR2(40), 
        "ZJ" VARCHAR2(20), 
        "JSZW" VARCHAR2(20), 
        "JSJB" VARCHAR2(20), 
        "GWGZ" NUMBER(6,2), 
        "MEMO" VARCHAR2(40), 
        "MODILEV" NUMBER(*,0) DEFAULT 0, 
        "STATION" NUMBER(5,0), 
         CONSTRAINT "PK_EMPLOYEE" PRIMARY KEY ("ID")
      USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX"  ENABLE, 
         CONSTRAINT "UK_EMPLOYEE" UNIQUE ("EMP_ID")
      USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX"  ENABLE
       ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
      STORAGE(INITIAL 196608 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP" ;

      CREATE UNIQUE INDEX "PK_EMPLOYEE" ON "EMPLOYEE" ("ID") 
      PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX" ;

      CREATE UNIQUE INDEX "UK_EMPLOYEE" ON "EMPLOYEE" ("EMP_ID") 
      PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX" ;

      ALTER TABLE "EMPLOYEE" ADD CONSTRAINT "PK_EMPLOYEE" PRIMARY KEY ("ID")
      USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX"  ENABLE;

      ALTER TABLE "EMPLOYEE" MODIFY ("EMP_ID" NOT NULL ENABLE);

      ALTER TABLE "EMPLOYEE" ADD CONSTRAINT "UK_EMPLOYEE" UNIQUE ("EMP_ID")
      USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX"  ENABLE;


      CREATE TABLE "SALARY" 
       (    "EMP_ID" VARCHAR2(5), 
        "ATT_MONTH" DATE, 
        "JXGZ" NUMBER(8,2), 
        "YCXJJ" NUMBER(8,2), 
        "BZZJT" NUMBER(8,2), 
        "YBJT" NUMBER(8,2), 
        "WQJT" NUMBER(8,2), 
        "JBGZ" NUMBER(8,2), 
        "QTJ" NUMBER(8,2), 
        "BF" NUMBER(8,2), 
        "GSKH" NUMBER(8,2), 
        "BMKH" NUMBER(8,2), 
        "TOTAL" NUMBER(8,2), 
        "MEMO" VARCHAR2(80), 
        "CHECKLOCK" VARCHAR2(1) DEFAULT '2', 
        "MODILOCK" NUMBER(*,0) DEFAULT 1, 
        "MODITIME" DATE, 
        "SGSFF" VARCHAR2(1) DEFAULT 0, 
        "CT" NUMBER(8,2), 
        "RCJB" NUMBER(8,2), 
        "XJFF" NUMBER(8,2), 
        "STATION" NUMBER(11,0), 
        "DEP_ID" VARCHAR2(5), 
        "ID" NUMBER(11,0), 
         CONSTRAINT "PK_SALARY" PRIMARY KEY ("EMP_ID", "ATT_MONTH")
      USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 196608 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX"  ENABLE
       ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
      STORAGE(INITIAL 327680 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP" ;

      CREATE UNIQUE INDEX "PK_SALARY" ON "SALARY" ("EMP_ID", "ATT_MONTH") 
      PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 196608 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX" ;

      ALTER TABLE "SALARY" ADD CONSTRAINT "PK_SALARY" PRIMARY KEY ("EMP_ID", "ATT_MONTH")
      USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 196608 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX"  ENABLE;


      CREATE TABLE "organization" 
       (    "IDParent" VARCHAR2(5) NOT NULL ENABLE, 
        "ID" VARCHAR2(5) NOT NULL ENABLE, 
        "ZJMC" VARCHAR2(60), 
        "ZJJS" VARCHAR2(50), 
         CONSTRAINT "PK_organization" PRIMARY KEY ("ID")
      USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX"  ENABLE
       ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP" ;

      CREATE UNIQUE INDEX "PK_organization" ON "organization" ("ID") 
      PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX" ;

      ALTER TABLE "organization" ADD CONSTRAINT "PK_organization" PRIMARY KEY ("ID")
      USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
      STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
      TABLESPACE "JXKP_INDEX"  ENABLE;

      ALTER TABLE "organization" MODIFY ("IDParent" NOT NULL ENABLE);

      ALTER TABLE "organization" MODIFY ("ID" NOT NULL ENABLE);

2 个答案:

答案 0 :(得分:0)

我试图简化您的查询,请看一下:

SELECT 
    yy.IDParent, 
    xx.ROOT_ID, 
    yy.name, 
    SUM(xx.heji) total
FROM (
    SELECT 
        CONNECT_BY_ROOT(t.ID) ROOT_ID,
        t.heji
    FROM    (
                SELECT 
                    dept.ID,
                    dept.IDParent,
                    dept.name,
                    NVL(bb.HJ, 0) as heji
                FROM organization dept LEFT OUTER JOIN
                         (SELECT 
                                att_month,
                                b.dep_id,
                                SUM(total) as HJ
                          FROM 
                                salary a INNER JOIN employee b ON b.emp_id = a.emp_id
                          WHERE 
                                TO_CHAR(att_month, 'yyyy-mm') = '2012-05'
                          GROUP BY 
                                att_month, 
                                b.dep_id
                         ) bb ON dept.ID = bb.dep_id
            ) t
     CONNECT BY PRIOR t.ID = t.IDParent
    ) xx INNER JOIN organization yy ON xx.ROOT_ID = yy.ID
GROUP BY 
    yy.IDParent, 
    xx.ROOT_ID, 
    yy.name;

答案 1 :(得分:0)

  • 使用COMPUTE STATISTICS
  • 在组织上添加索引:(IDParent)
  • 在工资上添加基于函数的索引:TO_CHAR(att_month,'yyyy-mm')

同样,由于您正在广泛地解析一堆表,因此不要忘记检查生成全局统计信息的时间。如果您决定再次生成它们,则在创建密钥时不必使用COMPUTE STATISTICS。

RGDS。