好的,这个问题有点难以解释,但在这里......
我有一个查询,它可以提取在树中呈现的数据,就像可视化一样。在此查询中计算的yloc用于确定y位置以呈现附加到这些功能的某些对象。
仅使用MAX(合并(CAP_TREE2.depth),0)不起作用。所以我写了一个算法,在某些情况下显示我需要的是什么。
以下是算法:
if (capability has c2 !=1)
{
yloc = 0
}
else if (capability is child (at any depth) of capability with c2 != 1)
{
yloc = depth - (depth of first parent with c2 != 1)
}
else
{
y = depth
}
注意: c2代表childNumber(按字母顺序排列)。因此,如果一个能力有两个孩子“A”和“B”。 “A”将具有c2 = 1并且“B”将具有c2 = 2。
我在尝试在SQL(Oracle 11g R2)中实现此算法时遇到了很多麻烦。 我在完成问题时遇到的问题是我的算法中的 else if 子句。 我已经能够通过c2!= 1获得所有功能的孩子(在任何深度)。
然而,我无法完成的部分是 yloc =深度 - (第一个父亲的深度为c2!= 1)
任何人都可以告诉我如何获得“c2的第一个父亲的深度!= 1”? 如果我能得到那个值,我的查询最终会完成。
我将展示我希望从我的样本数据中获得的值,以便更加清晰。
“投资管理”第一个父亲与c2!= 1是“FPP”,其深度为2。 具有c2!= 1的“第三方产品管理”第一父母是深度为2的“FPP”。 “订单管理(PI)”第一个父项c2!= 1是“操作和服务(PI)”,深度为2。
注意:抱歉,我无法更改架构。
这是我到目前为止所做的...最底层的选择陈述是我工作的地方。 http://sqlfiddle.com/#!4/55b5a/116
架构SQL:
CREATE TABLE capability
(
id int,
parent_id int,
name varchar(200)
)
;
CREATE TABLE tree
(
descendantid int,
ancestorid int,
depth int
)
;
INSERT INTO capability (id, parent_id, name) VALUES (1, -1, 'BU-Specific Capabilities');
INSERT INTO capability (id, parent_id, name) VALUES (2, 1, 'PI Capability Model');
INSERT INTO capability (id, parent_id, name) VALUES (3, 2, 'Core Business Processing (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (4, 3, 'Institutional Trust Administration (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (5, 2, 'FPP');
INSERT INTO capability (id, parent_id, name) VALUES (6, 5, 'Investment Management');
INSERT INTO capability (id, parent_id, name) VALUES (7, 6, '3rd party Product Management');
INSERT INTO capability (id, parent_id, name) VALUES (8, 2, 'Operations and Shared Services (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (9, 8, 'Order Management (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (10, 8, 'Settlements (PI)');
INSERT INTO capability (id, parent_id, name) VALUES (11, -1, 'Common Core Capabilities');
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (1, 1, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (2, 1, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (2, 2, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (3, 1, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (3, 2, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (3, 3, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (4, 1, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (4, 2, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (4, 3, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (4, 4, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (5, 1, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (5, 2, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (5, 5, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (6, 1, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (6, 2, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (6, 5, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (6, 6, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 1, 4);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 2, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 5, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 6, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (7, 7, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (8, 1, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (8, 2, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (8, 8, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (9, 1, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (9, 2, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (9, 8, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (9, 9, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (10, 1, 3);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (10, 2, 2);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (10, 8, 1);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (10, 10, 0);
INSERT INTO tree (descendantid, ancestorid, depth) VALUES (11, 11, 0);
查询SQL:
SELECT
cap.name,
max(coalesce(CAP_TREE2.depth,0)) as ydepth,
CASE
WHEN cap.parent_id != -1
THEN DENSE_RANK() OVER (PARTITION BY cap.parent_id ORDER BY cap.name) --child number
ELSE
1
END as c2
FROM capability cap
INNER JOIN tree CAP_TREE2 ON CAP.id = CAP_TREE2.descendantid
group by cap.name, cap.id, cap.parent_id
;
WITH ids(id, c2) AS ( -- Find the ids and the ranks
SELECT
id,
CASE
WHEN parent_id = -1
THEN 1
ELSE
DENSE_RANK() OVER (PARTITION BY parent_id ORDER BY name) --child number
END as c2
FROM capability
),
t(id, depth) AS (
SELECT id, 0 AS depth FROM ids WHERE c2 != 1 -- Take only ranks not equal to one
UNION ALL
SELECT c.id, depth+1 FROM capability c JOIN t ON (c.parent_id = t.id) -- Tree-walking
)
--SELECT DISTINCT cap.name, t.depth
--SELECT DISTINCT cap.name, min(t.depth)
--FROM capability cap JOIN t USING(id)
--group by cap.name
SELECT
cap.name,
CASE
-- cap has childNumber != 1
WHEN DENSE_RANK() OVER (PARTITION BY cap.parent_id ORDER BY cap.name) != 1
THEN 0 -- y = 0
-- cap is child of cap with childNumber != 1
WHEN cap.name IN (SELECT DISTINCT capa.name
FROM capability capa
JOIN t USING(id))
THEN max(coalesce(CAP_TREE2.depth,0)) -- y = depth - (depth of first parent with childNumber != 1)
ELSE max(coalesce(CAP_TREE2.depth,0)) -- y = depth
END as yloc
FROM capability cap
INNER JOIN tree CAP_TREE2 ON CAP.id = CAP_TREE2.descendantid
group by cap.name,
cap.id,
cap.parent_id
此外,这是我想要的结果集
NAME DEPTH C2 YLOC
BU-Specific Capabilities 0 1 0 --yloc=depth
Common Core Capabilities 0 1 0 --yloc=depth
PI Capability Model 1 1 1 --yloc=depth
Core Business Processing (PI) 2 1 2 --yloc=depth
FPP 2 2 0 --yloc=0
Operations and Shared Services (PI) 2 3 0 --yloc=0
Institutional Trust Administration (PI) 3 1 3 --yloc=depth
Investment Management 3 1 1 --yloc=depth - (depth of FPP)
3rd party Product Management 4 1 2 --yloc=depth - (depth of FPP)
Order Management (PI) 3 1 1 --yloc=depth -(depth of Operations and..)
Settlements (PI) 3 2 0 --yloc=0
答案 0 :(得分:1)
我认为您不需要树表,因为您已经在功能表中声明了从父级到子级的关系。
当您使用oracle中的 CONNECT BY PRIOR 命令时,它会为您构建树,并允许您使用 LEVEL 伪列来确定节点的深度。 / p>
唯一棘手的部分是获得深度为>的第一个父节点。据我所知,你的问题应该是c2。结果在列中 的 FIRST_PARENT_IN_DEPTH_G_1 即可。
SELECT ID
, PARENT_ID
, NAME
, DEPTH
, NODES_PER_LEVEL
, TO_NUMBER(SUBSTR(ID_PATH, LENGTH(REGEXP_SUBSTR(ID_PATH, '^\s\d{1,}\s')) + 1,
INSTR(SUBSTR(ID_PATH, LENGTH(REGEXP_SUBSTR(ID_PATH, '^\s\d{1,}\s')) + 1), ' ')))
AS FIRST_PARENT_IN_DEPTH_G_1
FROM (
SELECT ID
, PARENT_ID
, NAME
, LEVEL DEPTH
, COUNT(*) OVER (PARTITION BY PARENT_ID, LEVEL) NODES_PER_LEVEL
, sys_connect_by_path( id, ' ' ) ID_PATH
FROM capability
START WITH PARENT_ID = -1
CONNECT BY PRIOR ID = PARENT_ID
)
ORDER BY ID_PATH