2

ENV:postgresql-8.4PostgreSQL分层,分类树

我试图建立一个类别树。基本上我期待的最终输出是:

 
categoryName 
categoryPath 
leafcategory 

 
Digital Camera 
Electronics ::: Digital Camera 
true 

表结构是

 
CREATE TABLE categories (
    id SERIAL PRIMARY KEY, 
    categoryid bigint, 
    categoryparentid bigint, 
    categoryname text, 
    status integer DEFAULT 0, 
    lang text, 
    eysiteid text, 
    country text, 
    tempid text, 
    leafcategory boolean 
);

到目前为止,我已经得到了这一点,但不工作。任何帮助将高度赞赏:从数据库

 
cat=> select * from categories; 
    id | categoryid | categoryparentid |   categoryname   | status | lang | eysiteid | country | tempid | leafcategory 
-------+------------+------------------+--------------------------------+--------+------+------------+---------+--------+-------------- 
    1 |   -1 |    0 | Root       |  1 | en | 0   | us  |  | f 
    2 |  20081 |    -1 | Antiques      |  1 | en | 0   | us  |  | f 
    17 |  1217 |   20081 | Primitives      |  0 | en | 0   | us  |  | t 
    23 |  22608 |   20081 | Reproduction Antiques   |  0 | en | 0   | us  |  | t 
    24 |   12 |   20081 | Other       |  0 | en | 0   | us  |  | t 
    25 |  550 |    -1 | Art       |  1 | en | 0   | us  |  | f 
    29 |  2984 |    -1 | Baby       |  1 | en | 0   | us  |  | f 

+0

你有一种奇怪的方法来标记树的根节点(通常一个会有根的NULL父指针)。查看我的更新。 – wildplasser 2012-08-06 21:18:15

回答

2

看来你加入了错误的领域

 
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.category_tree = c.CategoryParentID) 
) 
SELECT * FROM tree ORDER BY category_tree; 

样品。

-- 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 

或m aybe甚至:

WHERE COALESCE(CategoryParentID, 0) = 0 
+0

我得不到结果(0行) – themihai 2012-08-06 19:48:43

+0

必须提到根类别的categoryparentid为0。 – themihai 2012-08-06 20:03:23

+1

您必须将父项设置为NULL,其中父<= 0; (或更改工会第一段中的where子句) – wildplasser 2012-08-06 20:07:09