我试图在PostgreSQL数据库中创建一个桥接表,遵循Kimball数据仓库工具包提到的here方法,这样我就可以支持不确定深度的层次结构。
基本思想是,如果您有节点的树层次结构,则需要一个表,该表为树中的每个可能路径都有一行。
首先,您可以创建父子关系表,如下所示:
BEGIN TRANSACTION;
Create table COMPANY (
COMPANY_KEY INTEGER NOT NULL,
COMPANY_NAME VARCHAR,
PARENT_KEY INTEGER);
INSERT INTO COMPANY VALUES (100,'MICROSOFT',NULL);
INSERT INTO COMPANY VALUES (101,'SOFTWARE',100);
INSERT INTO COMPANY VALUES (102,'CONSULTING',101);
INSERT INTO COMPANY VALUES (103,'PRODUCTS',101);
INSERT INTO COMPANY VALUES (104,'OFFICE',103);
INSERT INTO COMPANY VALUES (105,'VISIO',104);
INSERT INTO COMPANY VALUES (106,'VISIO EUROPE',105);
INSERT INTO COMPANY VALUES (107,'BACK OFFICE',103);
INSERT INTO COMPANY VALUES (108,'SQL SERVER',107);
INSERT INTO COMPANY VALUES (109,'OLAP SERVICES',108);
INSERT INTO COMPANY VALUES (110,'DTS',108);
INSERT INTO COMPANY VALUES (111,'REPOSITORY',108);
INSERT INTO COMPANY VALUES (112,'DEVELOPER TOOLS',103);
INSERT INTO COMPANY VALUES (113,'WINDOWS',103);
INSERT INTO COMPANY VALUES (114,'ENTERTAINMENT',103);
INSERT INTO COMPANY VALUES (115,'GAMES',114);
INSERT INTO COMPANY VALUES (116,'MULTIMEDIA',114);
INSERT INTO COMPANY VALUES (117,'EDUCATION',101);
END TRANSACTION;
从上面的文档中,他们建议使用以下代码从上面创建的表中构建桥表:
WITH REC (root_id, level, company_key, parent_key, company_name, unparsed_company_name)
AS (
SELECT company_key,
1,
company_key,
parent_key,
company_name,
CAST(company_name AS VARCHAR(250))
FROM company
WHERE parent_key IS NULL
UNION ALL
SELECT
rec.root_id,
rec.level + 1,
rec_plus1.company_key,
rec_plus1.parent_key,
rec_plus1.company_name,
TRIM(rec.unparsed_company_name)||'>'||TRIM(rec_plus1.company_name)
FROM company AS rec_plus1, rec
WHERE rec.company_key = rec_plus1.parent_key
)
SELECT
company_key,
parent_key,
company_name,
root_id,
level AS depth_from_parent,
COALESCE((SELECT 'N' FROM company s2 WHERE s1.company_key = s2.parent_key FETCH FIRST ROW ONLY), 'Y') AS lowest_flag,
(SELECT (CASE WHEN MAX (s2.level) = s1.level THEN 'Y' ELSE 'N' END) FROM rec s2 WHERE s1.root_id = s2.company_key) AS top_most_flag,
REPEAT('', level*5)||level||'-'||company_name AS company_logical_tree,
unparsed_company_name FROM rec s1;
我尝试将上述内容转换为PostgreSQL特定代码,如下所示:
BEGIN TRANSACTION;
CREATE TABLE company_bridge AS
WITH RECURSIVE rec (root_id, level, company_key, parent_key, company_name, unparsed_company_name)
AS (
SELECT company_key::integer,
1,
company_key::integer,
parent_key::integer,
company_name::varchar,
company_name::varchar
FROM company
WHERE parent_key IS NULL
UNION ALL
SELECT
rec.root_id,
rec.level + 1,
rec_plus1.company_key,
rec_plus1.parent_key,
rec_plus1.company_name,
(TRIM(rec.unparsed_company_name)||'>'||TRIM(rec_plus1.company_name))::varchar
FROM company AS rec_plus1, rec
WHERE rec.company_key = rec_plus1.parent_key
)
SELECT
company_key,
parent_key,
company_name,
root_id,
level AS depth_from_parent,
COALESCE((SELECT 'N'::varchar FROM company AS s2 WHERE s1.company_key = s2.parent_key FETCH FIRST ROW ONLY), 'Y'::varchar) AS lowest_flag,
(SELECT (CASE WHEN MAX (s2.level) = s1.level THEN 'Y'::varchar ELSE 'N'::varchar END) FROM rec AS s2 WHERE s1.root_id = s2.company_key) AS top_most_flag,
REPEAT('', level*5)||level||'-'||company_name AS company_logical_tree,
unparsed_company_name FROM rec AS s1;
ALTER TABLE company_bridge ADD PRIMARY KEY (company_key);
END TRANSACTION;
然而,这会产生这个输出,它只有从每个父节点到其直接子节点的行:
我需要的是每个父节点到它下面的每个节点的一行。为了帮助实现这一点,以上表格绘制为树形图:
从顶部节点100开始,它应该有一行:100-100(本身),100-> 101,100-> 102,100-> 103 ...一直到100 - > 117 - 即树中的每个节点。下一个节点101对于它下面的每个节点应该具有相同的,包括其自身:101-> 101,101-> 102 ... 101-> 117。树下面的节点,如108,将具有:108-> 108,108-> 109,108-> 110和108-> 111.
我只是习惯在Postgres中使用递归,所以我很难诊断出问题所在。有什么想法吗?