3

环境:postgresql-8.4

我正在尝试构建类别树。基本上我期待最终输出,例如:

分类名称
类别路径
叶类
例如:

数码相机
电子产品 ::: 数码相机
真的

表结构为

创建表类别(
    id 序列主键,
    分类号 bigint,
    categoryparentid bigint,
    类别名称文本,
    状态整数 DEFAULT 0,
    朗文字,
    eysiteid 文本,
    国家文本,
    温文尔雅的文字,
    叶类别布尔值
);

到目前为止,我已经得到了这个,但没有工作。任何帮助将不胜感激:

WITH RECURSIVE 树(CategoryID、CategoryParentID、CategoryName、category_tree、depth)
作为 (
    选择
        类别ID,
        类别父 ID,
        分类名称,
        类别名称 AS 类别树,
        0 AS 深度
    从类别
    其中 CategoryParentID 为 NULL
联合所有
    选择
        c.CategoryID,
        c.CategoryParentID,
        c.类别名称,
        树.category_tree || '/' || c.CategoryName AS category_tree,
        depth+1 AS 深度
    从树
        加入类别 c ON (tree.category_tree = c.CategoryParentID)
)
SELECT * FROM tree ORDER BY category_tree;

来自数据库的样本

cat=> 从类别中选择 *;
  编号 | 类别ID | 类别父ID | 类别名称 | 状态 | 朗 | eysiteid | 国家 | 胆小| 叶类
--------+------------+------------------+------------ ----------+--------+------+------------ -+---------+--------+--------------
     1 | -1 | 0 | 根 | 1 | zh | 0 | 我们 | | F
     2 | 20081 | -1 | 古董 | 1 | zh | 0 | 我们 | | F
    17 | 第1217章 20081 | 原语 | 0 | zh | 0 | 我们 | | 吨
    23 | 22608 | 20081 | 复制古董 | 0 | zh | 0 | 我们 | | 吨
    24 | 12 | 20081 | 其他 | 0 | zh | 0 | 我们 | | 吨
    25 | 550 | -1 | 艺术 | 1 | zh | 0 | 我们 | | F
    29 | 2984 | -1 | 宝贝 | 1 | zh | 0 | 我们 | | F

4

2 回答 2

3

您似乎加入了错误的领域。

 --  create some test data
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE categories
    -- ( id  SERIAL PRIMARY KEY
    ( categoryid SERIAL PRIMARY KEY
    , categoryparentid bigint REFERENCES categories(categoryid)
    , categoryname text
    -- , status integer DEFAULT 0
    -- , lang text
    -- , ebaysiteid text
    -- , country text
    -- , tempid text
    -- , leafcategory boolean
        );
INSERT INTO categories(categoryid,categoryparentid) SELECT gs, 1+(gs/6)::integer
FROM generate_series(1,50) gs;

UPDATE categories SET categoryname = 'Name_' || categoryid::text;
UPDATE categories SET categoryparentid = NULL WHERE categoryparentid <= 0;
UPDATE categories SET categoryparentid = NULL WHERE categoryparentid  >= categoryid;


WITH RECURSIVE tree (categoryid, categoryparentid, categoryname, category_tree, depth)
AS (
    SELECT
        categoryid
        , categoryparentid
        , categoryname
        , categoryname AS category_tree
        , 0 AS depth
    FROM categories
    WHERE categoryparentid IS NULL
UNION ALL
    SELECT
        c.categoryid
        , c.categoryparentid
        , c.categoryname
        , tree.category_tree  || '/' || c.categoryname AS category_tree
        , depth+1 AS depth
    FROM tree
        JOIN categories c ON tree.categoryid  = c.categoryparentid
    )
SELECT * FROM tree ORDER BY category_tree;

编辑:递归的另一个(“非函数”)表示法似乎效果更好:

WITH RECURSIVE tree AS (
    SELECT
        categoryparentid AS parent
        , categoryid AS self
        , categoryname AS treepath
        , 0 AS depth
    FROM categories
    WHERE categoryparentid IS NULL
UNION ALL
    SELECT
        c.categoryparentid AS parent
        , c.categoryid AS self
        , t.treepath  || '/' || c.categoryname AS treepath
        , depth+1 AS depth
    FROM categories c
    JOIN tree t ON t.self  = c.categoryparentid
    )
SELECT * FROM tree ORDER BY parent,self
   ;

更新:在原始查询中,您应该替换

WHERE CategoryParentID IS NULL

经过:

WHERE CategoryParentID = 0

甚至可能:

WHERE COALESCE(CategoryParentID, 0) = 0
于 2012-08-06T19:35:30.967 回答
0

看看这个要点它或多或少是你想要做的。在您的情况下,我最好使用LTree 物化路径 Postgresql's extension

于 2012-08-21T15:51:52.263 回答