如何使用 VIEW 将 Postgresql ltree 结构转换为嵌套集?

vpe*_*igo 8 postgresql hierarchy postgresql-9.4

我想问一个关于仅使用VIEWs将 PostgreSQL ltree 结构转换为仅具有一个查询的嵌套集结构的方法的问题。

例如,我有一个表,其中包含相互关联的数据,如下图所示:

表结构

所以,表声明是

KeywordLtree(id INT PRIMARY KEY, value TEXT, path ltree);

-- And the data is:

pk |  value  |  path  |
0  |   'A'   |   ''   |
0  |   'B'   |   '1'  |
0  |   'C'   |   '2'  |
0  |   'D'   |  '1.3' |
0  |   'E'   |  '1.4' |
0  |   'F'   |  '1.5' |
0  |   'G'   |  '2.6' |
0  |   'H'   |  '2.7' |
Run Code Online (Sandbox Code Playgroud)

我必须将此表转换为这样的表:

KeywordSets(id INT PRIMARY KEY, value TEXT, lft INT, rgt INT);
Run Code Online (Sandbox Code Playgroud)

其中左右边框的规则是根据嵌套集规则完成的。我找到了如何在每个级别上获取顶点的方法

CREATE OR REPLACE RECURSIVE VIEW bfs (id, value, path, num_on_level, level) AS
    SELECT id, value, path, row_number() OVER (), 0 as level
    FROM KeywordLtreeSandbox WHERE path ~ '*{0}'

    UNION ALL

    SELECT C.id, C.value, C.path, row_number() OVER (PARTITION BY P.path), level + 1 
    FROM KeywordLtreeSandbox C JOIN bfs P ON P.path @> C.path 
    WHERE nlevel(C.path) = level + 1;

-- Data would be like below
id | value | path | num_on_level | level |
0  |  "A"  |  ""  |      1       |   0   |
1  |  "B"  | "1"  |      1       |   1   |
2  |  "C"  | "2"  |      2       |   1   |
3  |  "D"  |"1.3" |      1       |   2   |
4  |  "E"  |"1.4" |      2       |   2   |
5  |  "F"  |"1.5" |      3       |   2   |
6  |  "G"  |"2.6" |      1       |   2   |
7  |  "H"  |"2.7" |      2       |   2   |
Run Code Online (Sandbox Code Playgroud)

但我不知道如何正确枚举它们(所以“A”左 = 1,右 = 16,“B”左 = 2,右 = 9 等等......)

如果我需要更清楚,请告诉我。

谁能给我一个想法怎么做?

ype*_*eᵀᴹ 5

我认为有一种不使用递归查询的方法可以解决这个问题:

WITH cte AS
  ( SELECT 
        m.*, 
        ( SELECT COUNT(*) 
          FROM KeywordLtree AS d
          WHERE m.path @> d.path
        ) AS descendants,
        ( SELECT COUNT(*) 
          FROM KeywordLtree AS a
          WHERE a.path @> m.path
        ) AS ancestors,
        ROW_NUMBER() OVER (ORDER BY m.path) AS rn
    FROM KeywordLtree AS m
  ) 
SELECT cte.*, 
       2 * rn - ancestors AS lft,
       2 * rn - ancestors + 2 * descendants - 1 AS rgt
FROM cte
ORDER BY path ;
Run Code Online (Sandbox Code Playgroud)