Oracle - 分层数据的相邻汇总

Oracle - Adjacent Rollup of Hierarchial Data

Oracle 12c R1 - 我正在尝试为销售组织构建仪表板。具体来说,它用于销售预测(也称为销售管道)。涉及两个 table,一个名为 IB_HIERARCHY_S 的销售代表层级 table 和一个名为 ALL_DEAL 的销售预测 table。

IB_HIERARCHY_S table 与 Oracle 附带的传统 EMP table 非常相似……代表没有员工 ID,而是有区域 ID,他的区域ID 汇总到其经理的区域 ID。它在销售层次结构中每人一行,上下导航层次结构的方式是 TERRITORY_ID = PARENT_TERRITORY_ID。它包括整个销售组织,从最低的代表到经理,再到组织副总裁。这个层次结构大约有 6 级深度。

IB_HIERARCHY_S structure

TERRITORY_ID  - primary key
EMAIL_ADDRESS –  email address of the rep
PAR_TERR_ID – parent territory ID, aka the territory ID of this person’s manager
…

另一个table是ALL_DEAL。这是销售预测 table。每个销售机会将在此 table.

中占一行
ALL_DEAL structure

FIELD_REP_E_MAIL – email address of the rep.
TERRITORY_ID – Territory ID of the rep who is forecasting the deal
FISCAL_QUARTER – the quarter the deal is expected to close
TERRITORY_LOB – The line of business who is actively working the deal, Field rep of Telesales Rep
REV_TYPE – One of 6 buckets for the revenue
PIPE – a forecast dollar amount

问题与 showing/comparing 树的多个部分相互冲突有关。显示单个代表的表现很容易……显示一个代表与同龄人的表现比较有挑战性。真正的问题是将不处于代表级别的同行相互比较,因为您必须 "rollup" 和层次结构中位于他们下方的每个人的 PIPE。假设副总裁有 3 个直接下属,“Mgr-A”、“Mgr-B”和“Mgr-C”。使用此仪表板的人将输入“Mgr-A”的电子邮件地址,并希望查看该经理与“Mgr-B”和“Mgr-C”的比较情况。我们需要找到 Mgr-A 的对等点,然后为所有这些对等点汇总层次结构中位于它们下方的每个人的数据。

我可以用这个找到同行SQL

SELECT  TERRITORY_ID
        FROM IB_HIERARCHY_S
where par_terr_id in 
(select par_terr_id FROM IB_HIERARCHY_S 
     where email_address = 'Mgr-A');

这将 return Mgr-A、Mgr-B 和 Mgr-C 的区域 ID。我的问题是如何汇总 Mgr-A、Mgr-B 和 Mgr-C 下每个人各自的销售渠道?

这是我目前所拥有的,但它没有考虑到 Mgr-A、Mgr-B 和 Mgr-C 是组织树的一部分,并且它们下面的数据需要"rolled up"。

with peer_list as
 ( SELECT  TERRITORY_ID
        FROM IB_HIERARCHY_S
where par_terr_id in (select par_terr_id FROM IB_HIERARCHY_S where email_address = 'Mgr-A')
  )
select territory_id, fiscal_quarter, territory_lob, rev_type, sum(pipe) as PIPE,
grouping(field_rep_e_mail) as grp_email,
grouping(fiscal_quarter) as grp_1,
grouping(territory_lob) as grp_2,
grouping(rev_type) as grp_3
from smb.all_deal
where fiscal_quarter =  'FY18-Q2'
and TERRITORY_ID in (select territory_ID from peer_list)
group by rollup(territory_id, fiscal_quarter, territory_lob, rev_type)
order by territory_id, fiscal_quarter, territory_lob, rev_type;

感谢任何帮助或想法。

回答

最终的工作是识别(通过 CONNECT BY 查询)所有根电子邮件和所有叶电子邮件。然后我在叶子电子邮件中总结 ALL_DEAL,但按根电子邮件分组。

with peer_list as
 (SELECT  distinct email_address,             
        REGEXP_SUBSTR (SYS_CONNECT_BY_PATH(territory_id, '/'), '[^/]+', 1, 1)  Root_Terr_Id,
        REGEXP_SUBSTR (SYS_CONNECT_BY_PATH(email_address, '/'), '[^/]+', 1, 1)  Root_Email
        FROM IB_HIERARCHY_S
        START WITH territory_id in 
(SELECT  TERRITORY_ID
        FROM IB_HIERARCHY_S
       where par_terr_id in 
      (select par_terr_id FROM IB_HIERARCHY_S 
      where email_address = 'Mrg-A'))
        CONNECT BY PRIOR territory_id = par_terr_id
order by email_address
  )
select <data> from ALL_DEAL, PEER_LIST
...

您需要创建一个内联视图(子查询)来显示所有对等节点及其下的子树。然后将此视图加入 ALL_DEAL table 并按原样进行所有聚合;您还需要按 PEER.

分组

为了展示如何创建我之前提到的内联视图,我将使用标准 SCOTT 架构中的 EMP table。假设我想为员工 7566 创建视图。(这可以是硬编码的,也可以是绑定变量;或者,您可以为每个人创建一个 table 并只进行一次所有计算,创建一个物化从里面看,再对比分析都是从这个大MV中读取数据。)

所以:员工7566。我怎样才能得到这个员工和他的同事的table,并显示每个同事下的所有员工?方法如下。使用分层查询的 connect_by_root 伪列。

select connect_by_root(empno) as peer, empno
from emp
connect by mgr = prior empno
start with empno in ( select empno 
                      from   emp
                      where  mgr = (select mgr from emp where empno = 7566)
                    )
;

PEER  EMPNO
----  ----
7566  7566
7566  7788
7566  7876
7566  7902
7566  7369
7698  7698
7698  7499
7698  7521
7698  7654
7698  7844
7698  7900
7782  7782
7782  7934