0

Sample database (Categories in a Nested Set Model):

CREATE TABLE `category` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL DEFAULT '',
    `lft` int(11) NOT NULL,
    `rgt` int(11) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

INSERT INTO category(name, lft, rgt) values("Primary", 0, 1000);
INSERT INTO category(name, lft, rgt) values("Secondary", 1, 500);
INSERT INTO category(name, lft, rgt) values("Tertiary", 2, 20);
INSERT INTO category(name, lft, rgt) values("Tertiary2", 21, 30);

I want to obtain all the parents of the bottom child categories (probably concat?) like this:

Primary > Secondary > Tertiary
Primary > Secondary > Tertiary2

Besides playing with BETWEEN lft AND rgt and CONCAT, i'm pretty stuck and could use some tips and information about getting the required results. Thanks!

SQL Fiddle

Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
Pim Reijersen
  • 1,123
  • 9
  • 33
  • Read Bill Karwins slides to [SQL antipatterns](http://de.slideshare.net/billkarwin/sql-antipatterns-strike-back), slide 67 especially. – VMai May 13 '14 at 21:45
  • 1
    gotta admit I don't see the hierachy. I don't see how you get to primary from secondary nor do I see how to get from Tertiary to secondary given the lft and rgt values. some sort of recursive cte might work but I don't think mysql supports hierichal queries like that... – xQbert May 13 '14 at 21:47
  • The current database structure is no use to me if I can't get the required result out of it. If you have solutions that needs changes to the database tables I would still very much like to see them. – Pim Reijersen May 13 '14 at 22:09

2 Answers2

2

How about following query?

SELECT 
  GROUP_CONCAT(parent.name SEPARATOR '/') as parent_name
FROM category AS node,
        category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.lft;

Will return the requested output:

Primary
Primary > Secondary
Primary > Secondary > Tertiary
Primary > Secondary > Tertiary2

Testable @ http://sqlfiddle.com/#!9/4f4e97/2

In case you only want the leaf nodes

If I read correctly the original question your expected output should be:

Primary > Secondary > Tertiary
Primary > Secondary > Tertiary2

This is possible to achieve easily too by modifying the above query slightly to following:

SELECT 
  GROUP_CONCAT(parent.name SEPARATOR '/') as parent_name
FROM category AS node,
        category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.lft, node.rgt
HAVING node.lft = (node.rgt - 1)
ORDER BY node.lft;

This however assumes that all your leaf nodes (as they should) have rgt = lft + 1 !!

Test @ http://sqlfiddle.com/#!9/57acd4/1

0

Check out this excellent article on Managing Heirarchial Data by Mike Hillyer.

It explains quite a good method of not only structuring you data but also how to query and manipulate it including some differences between Adjacency List model and Nested Set model.

  • Table structure
  • How to query it in various ways
    • Finding Nodes, Paths and Full Tree results
  • Handling insertion of new data
  • Handling deletion of data

Finally, I realise this article doesn't expressly answer your requirement of generating results like these directly in SQL.

Primary > Secondary > Tertiary
Primary > Secondary > Tertiary2

You probably won't find much good reading on any decent ways of doing this without expensive loops or terribly difficult to maintain queries.

Typically this is done on an application level as generally those languages are much more suited for it (and when you can query your data you can produce depth values which make this looping quite easy to do).

Alex.Ritna
  • 1,957
  • 2
  • 16
  • 24
  • What are your ideas on this solution? http://karwin.blogspot.nl/2010/03/rendering-trees-with-closure-tables.html – Pim Reijersen May 13 '14 at 23:42
  • Closure Tables aren't a bad solution and do have some benefits as noted on that link and in the link above, I had presumed after @VMai had mentioned them and you skipped over his comment you found them unsuitable. – Alex.Ritna May 13 '14 at 23:48
  • I'm not sure yet. I'm going to give Closure Tables a try, as well as constructing the data in PHP from my current database as you suggested. Its the first time relational design is working against me so i'm exploring my options and opinions of people with more experience. – Pim Reijersen May 13 '14 at 23:54
  • The closure model will allow you to keep your referential integrity and make CRUD of nodes a bit easier. – Alex.Ritna May 14 '14 at 00:02