【问题标题】:How to get the accumulated sum of the children in an Hierarchical tree?如何获得分层树中孩子的累积总和?
【发布时间】:2012-06-05 02:11:27
【问题描述】:

表“salary”的列是 att_month、emp_id(指向员工的 emp_id)、total。
表“组织”列是 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);

【问题讨论】:

  • 您显然在使用 Oracle,因为 (+) 外连接表示法。但是,您的第一步应该是使用常规连接表示法重写查询,包括适当的内部和外部。 CONNECT BY PRIOR 的两个级别也不容易理解正在发生的事情。坦率地说,寻找我什至想开始考虑了解它在做什么都太令人费解了(而且我对 SQL 问题的痛苦阈值相当高)。
  • 请提供创建表语句、一些示例行和预期输出。
  • 请问,从概念上讲,什么是“组织”?什么是组织的父级?是“持有”的概念吗?
  • 这是一个离题的侧边栏,不是您问题的答案。如果使用嵌套集而不是邻接列表来组织数据,那么查询将非常简单。我意识到你必须按照你所得到的去做。

标签: sql oracle


【解决方案1】:

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

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;

【讨论】:

  • 你简化了什么?您的新查询将完成什么?你测试了吗?
  • 您好,我发现了一些不必要的操作。但不幸的是,我没有你的模型或数据来试用它。我仍然认为它可以帮助您进行表演。但是,我假设您需要的是所有上级组织及其子组织 2012 年 5 月的累计总工资。
  • 你的结果和我的一样。我已经测试过了。我想我已经表达清楚了,你的假设正是我的想法。非常感谢!
  • 你的结果和我的一样,你的比我的快4倍左右。完美。我已经测试过了。我想我已经表达清楚了,你的假设正是我的想法。非常感谢!
  • 太棒了!而且我相信我们可以更深入地详细了解您的表结构 :) 如果这是您工作中的关键查询,我将很高兴与您一起走得更远......为了好玩:-)
【解决方案2】:
  • 在组织中添加索引:(IDParent),使用 COMPUTE STATISTICS
  • 为薪水添加基于函数的索引:TO_CHAR(att_month, 'yyyy-mm')

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

rgds.

【讨论】:

  • 我在更好地检查了你的结构后编辑了这个答案!现在应该很好了:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-08
  • 2021-07-22
  • 1970-01-01
  • 2023-03-16
  • 2018-09-05
  • 2022-01-13
  • 2018-05-30
相关资源
最近更新 更多