order sql tree hierarchy

前端 未结 8 1532
野的像风
野的像风 2020-12-05 03:30

What is the best way to sort a table like this:

CREATE TABLE category(
    id INT(10),
    parent_id INT(10),
    name VARCHAR(50)
);

INSERT INTO category (         


        
相关标签:
8条回答
  • 2020-12-05 03:39
    SELECT * FROM category ORDER BY name, parent_id ASC
    
    0 讨论(0)
  • 2020-12-05 03:40

    Sql

    WITH CTE_Category
        AS
        (
          SELECT id, parent_id, name
          , RIGHT(name,CHARINDEX(' ',REVERSE(RTRIM(name)))-1) as ordername
          FROM Category 
        )
    
        SELECT id, parent_id, name FROM CTE_Category ORDER BY ordername
    

    MySql

    SELECT id, parent_id, name
    FROM Category ORDER BY SUBSTRING_INDEX(name,' ',-1)
    
    0 讨论(0)
  • 2020-12-05 03:41

    By adding a path column and a trigger, this can be done fairly easily.

    First add a varchar column that will contain the path from root to the node:

    ALTER TABLE category ADD path VARCHAR(50) NULL;
    

    Then add a trigger that calculates the path on insert:

    (simply concats the new id with path of the parent)

    CREATE TRIGGER set_path BEFORE INSERT ON category
      FOR EACH ROW SET NEW.path = 
      CONCAT(IFNULL((select path from category where id = NEW.parent_id), '0'), '.', New.id);
    

    Then simply select order by path:

    SELECT name, path FROM category ORDER BY path;
    

    Result:

    pizza         0.1
    piperoni      0.1.4
    cheese        0.1.5
    extra cheese  0.1.5.7
    vegetariana   0.1.6
    burger        0.2
    coffee        0.3
    

    See fiddle.

    This way maintenance cost is also minimal. The path field is hidden when inserting and is calculated via trigger. Removing a node has no overhead, since all the children of the node are also removed. The only problem is when updating the parent_id of a node; Well, don't do that! :)

    0 讨论(0)
  • 2020-12-05 03:49

    I think everyone is over-architect-ing the solution. If your goal is really represented by your example, as in 3-levels with the virtual top level of 0 id, this should suffice.

    SELECT *
         , id AS SORT_KEY
      FROM category a
     WHERE parent_id = 0
    UNION ALL
    SELECT a.*
         , CONCAT(b.id, '.', a.id) AS SORT_KEY
      FROM category a
         , category b
     WHERE b.parent_id = 0
       and b.id = a.parent_id
    UNION ALL
    SELECT a.*
         , CONCAT(c.id,'.', b.id,'.', a.id) AS SORT_KEY
      FROM category a
         , category b
         , category c
     WHERE c.parent_id = 0
       and b.id = a.parent_id
       AND c.id = b.parent_id
    ORDER BY sort_key
    
    0 讨论(0)
  • 2020-12-05 03:49

    Try ORDER BY name , id at the end of your SQL query.

    This will sort by name and use id to settle any ties.

    0 讨论(0)
  • One way is to have separate string field for storing the full-path of any node. You need to maintain this field on every insert/update/delete operation.

    You can have field value like below

    CREATE TABLE category(
        id INT(10),
        parent_id INT(10),
        name VARCHAR(50),
        path VARCHAR(255)
    );
    
    INSERT INTO category (id, parent_id, name, path) VALUES
    (1, 0, 'pizza 1','|1|'),
    (2, 0, 'burger 2','|2|'),
    (3, 0, 'coffee 3','|3|'),
    (4, 1, 'piperoni 1.1','|1||4|'),
    (5, 1, 'cheese 1.2','|1||5|'),
    (6, 1, 'vegetariana 1.3','|1||6|'),
    (7, 5, 'extra cheese 1.2.1','|1||5||1|');
    

    You need to order by path field to have tree in proper sorting order.

    SELECT * FROM `category` ORDER BY `path`;
    

    See SqlFiddle Demo

    This way you do not need recursion in programming language to print the entire tree in correct sort order.

    Note:

    This example will only work if you have max ID upto 9, as |1||11| will come earlier than |1||2|

    To resolve this issue, you need to do padding for building string based on maximum value of ID field is expected for your application, like below example with max value expected is 999 (3 digits)

    |001||002|


    As per my experience this solution should only be good to handle tree with depth up-to 7-8 level.

    For Other method : Click Here

    0 讨论(0)
提交回复
热议问题