ENV : postgresql-8.4
I'm trying to build a category tree . Basically I'm expecting a final output such :
categoryName categoryPath leafcategorye.g. :
Digital Camera Electronics ::: Digital Camera true
The table structure is
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
);
So far I've got this but is not working. Any help would be highly appreciated :
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;
Sample from database
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
It appears you were joining on the wrong field.
-- 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;
EDIT: the other ("non-function") notation for recursive seems to work better:
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
;
UPDATE: in the original query, you should replace
WHERE CategoryParentID IS NULL
by:
WHERE CategoryParentID = 0
or maybe even:
WHERE COALESCE(CategoryParentID, 0) = 0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With