Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4051494
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 20, 20262026-05-20T14:12:07+00:00 2026-05-20T14:12:07+00:00

Hi For many days I have been working on this problem in MySQL, however

  • 0

Hi For many days I have been working on this problem in MySQL, however I can not figure it out. Do any of you have suggestions?

Basically, I have a category table with domains like: id, name (name of category), and parent (id of parent of the category).

Example Data:

1  Fruit        0
2  Apple        1
3  pear         1
4  FujiApple    2
5  AusApple     2
6  SydneyAPPLE  5
....

There are many levels, possibly more than 3 levels. I want to create an sql query that groups the datas according to he hierarchy: parent > child > grandchild > etc.

It should output the tree structure, as follows:

1 Fruit 0
 ^ 2 Apple 1
   ^ 4 FujiApple 2
   - 5 AusApple 2
     ^ 6 SydneyApple 5
 - 3 pear 1

Can I do this using a single SQL query? The alternative, which I tried and does work, is the following:

SELECT * FROM category WHERE parent=0

After this, I loop through the data again, and select the rows where parent=id. This seems like a bad solution. Because it is mySQL, CTEs cannot be used.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-20T14:12:07+00:00Added an answer on May 20, 2026 at 2:12 pm

    You can do it in a single call from php to mysql if you use a stored procedure:

    Example calls

    mysql> call category_hier(1);
    
    +--------+---------------+---------------+----------------------+-------+
    | cat_id | category_name | parent_cat_id | parent_category_name | depth |
    +--------+---------------+---------------+----------------------+-------+
    |      1 | Location      |          NULL | NULL                 |     0 |
    |      3 | USA           |             1 | Location             |     1 |
    |      4 | Illinois      |             3 | USA                  |     2 |
    |      5 | Chicago       |             3 | USA                  |     2 |
    +--------+---------------+---------------+----------------------+-------+
    4 rows in set (0.00 sec)
    
    
    $sql = sprintf("call category_hier(%d)", $id);
    

    Hope this helps 🙂

    Full script

    Test table structure:

    drop table if exists categories;
    create table categories
    (
    cat_id smallint unsigned not null auto_increment primary key,
    name varchar(255) not null,
    parent_cat_id smallint unsigned null,
    key (parent_cat_id)
    )
    engine = innodb;
    

    Test data:

    insert into categories (name, parent_cat_id) values
    ('Location',null),
       ('USA',1), 
          ('Illinois',2), 
          ('Chicago',2),  
    ('Color',null), 
       ('Black',3), 
       ('Red',3);
    

    Procedure:

    drop procedure if exists category_hier;
    
    delimiter #
    
    create procedure category_hier
    (
    in p_cat_id smallint unsigned
    )
    begin
    
    declare v_done tinyint unsigned default 0;
    declare v_depth smallint unsigned default 0;
    
    create temporary table hier(
     parent_cat_id smallint unsigned, 
     cat_id smallint unsigned, 
     depth smallint unsigned default 0
    )engine = memory;
    
    insert into hier select parent_cat_id, cat_id, v_depth from categories where cat_id = p_cat_id;
    
    /* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */
    
    create temporary table tmp engine=memory select * from hier;
    
    while not v_done do
    
        if exists( select 1 from categories p inner join hier on p.parent_cat_id = hier.cat_id and hier.depth = v_depth) then
    
            insert into hier 
                select p.parent_cat_id, p.cat_id, v_depth + 1 from categories p 
                inner join tmp on p.parent_cat_id = tmp.cat_id and tmp.depth = v_depth;
    
            set v_depth = v_depth + 1;          
    
            truncate table tmp;
            insert into tmp select * from hier where depth = v_depth;
    
        else
            set v_done = 1;
        end if;
    
    end while;
    
    select 
     p.cat_id,
     p.name as category_name,
     b.cat_id as parent_cat_id,
     b.name as parent_category_name,
     hier.depth
    from 
     hier
    inner join categories p on hier.cat_id = p.cat_id
    left outer join categories b on hier.parent_cat_id = b.cat_id
    order by
     hier.depth, hier.cat_id;
    
    drop temporary table if exists hier;
    drop temporary table if exists tmp;
    
    end #
    

    Test runs:

    delimiter ;
    
    call category_hier(1);
    
    call category_hier(2);
    

    Some performance testing using Yahoo geoplanet places data

    drop table if exists geoplanet_places;
    create table geoplanet_places
    (
    woe_id int unsigned not null,
    iso_code  varchar(3) not null,
    name varchar(255) not null,
    lang varchar(8) not null,
    place_type varchar(32) not null,
    parent_woe_id int unsigned not null,
    primary key (woe_id),
    key (parent_woe_id)
    )
    engine=innodb;
    
    mysql> select count(*) from geoplanet_places;
    +----------+
    | count(*) |
    +----------+
    |  5653967 |
    +----------+
    

    so that’s 5.6 million rows (places) in the table let’s see how the adjacency list implementation/stored procedure called from php handles that.

         1 records fetched with max depth 0 in 0.001921 secs
       250 records fetched with max depth 1 in 0.004883 secs
       515 records fetched with max depth 1 in 0.006552 secs
       822 records fetched with max depth 1 in 0.009568 secs
       918 records fetched with max depth 1 in 0.009689 secs
      1346 records fetched with max depth 1 in 0.040453 secs
      5901 records fetched with max depth 2 in 0.219246 secs
      6817 records fetched with max depth 1 in 0.152841 secs
      8621 records fetched with max depth 3 in 0.096665 secs
     18098 records fetched with max depth 3 in 0.580223 secs
    238007 records fetched with max depth 4 in 2.003213 secs
    

    Overall i’m pretty pleased with those cold runtimes as I wouldn’t even begin to consider returning tens of thousands of rows of data to my front end but would rather build the tree dynamically fetching only several levels per call. Oh and just incase you were thinking innodb is slower than myisam – the myisam implementation I tested was twice as slow in all counts.

    More stuff here : http://pastie.org/1672733

    Hope this helps 🙂

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I've been trying to figure this problem out for the last 2 days already,
Hi I have been searching a solution to this problem for many days but
Many times we find ourselves working on a problem, only to figure out the
This has been driving me crazy for 2 days. I have been trying to
Hi I have been trying to get this script http://jsbin.com/ipajo5/ working but using .live()
It’s been days that I’m working on a project which I have to use
I have this DateTime object: model.Model.Results.FloatingComponent().Schedule.ScheduleRows[0].Payment.FromDate.AdjustedDate How do I find out how many days
I am trying to find how many days are between two dates. I have
I have been out of the loop with web development for about a year
Let's say you work 100 days on a project. How many days would each

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.