E T
E T

Reputation: 381

Find Nodes in SQL Tree Structure

I have a tree-like data model stored in a MYSQL database. The tree is traversed by using two fields on each 'node' object:

The root id has a parent_id of 'null' and all other nodes in the tree reference a parent id.

If I want to get a list of all node ids in this tree, I have to recursively traverse the tree and collect one or more attributes of each node, using what is essentially a for loop with many queries.

I was wondering if there was a way to do this all more efficiently with on query in SQL

Upvotes: 1

Views: 1996

Answers (2)

Bill Karwin
Bill Karwin

Reputation: 562230

I wrote a highly-rated post about a solution I call Closure Table: What is the most efficient/elegant way to parse a flat table into a tree?

I also cover that design in my presentation Models for Hierarchical Data with SQL and PHP and in my book SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.

And I've answered questions about hierarchical-data queries many times on Stack Overflow: https://stackoverflow.com/search?q=user%3A20860+%5Bhierarchical-data%5D

Quassnoi has written an epic series of blog articles about querying trees in MySQL: http://explainextended.com/2009/07/22/hierarchial-queries-in-mysql-identifying-trees/

Quassnoi has also answered a number of questions on Stack Overflow about hierarchical-data: https://stackoverflow.com/search?q=user%3A55159+%5Bhierarchical-data%5D

Upvotes: 2

sgeddes
sgeddes

Reputation: 62831

You are using a difficult model for searching, the Adjacency List Model. If you know the number of potential "levels" of parent-to-child relationships you will have, then yes, you can construct a query to do so. However, if it's not a finite number, then it's going to be pretty difficult.

Consider using the Nested Set Model if possible. Here is a good article on the subject:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

Back to your question, you would have to join on the same table multiple times to get your desired results, something like this:

SELECT *
FROM YourTable t
    LEFT JOIN YourTable t2 ON t2.parentid = t1.id
    LEFT JOIN YourTable t3 ON t3.parentid = t2.id
    LEFT JOIN YourTable t4 ON t4.parentid = t3.id

With an additional JOIN for each potential child-parent relationship.

Hope this helps and good luck.

Upvotes: 1

Related Questions