Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sql query for tree table

I have a table with tree structure:

id parentId name
----------------
1  0        Category1
2  0        Category2
3  1        Category3
4  2        Category4
5  1        Category5
6  2        Category6
7  3        Category7

In sql query resut I need a table like:

id parentId level name
----------------------
1  0        0     Category1
3  1        1     Category3
7  3        2     Category7
5  1        1     Category5
2  0        0     Category2
4  2        1     Category4
6  2        1     Category6

Who can help me to write ms-sql query? Thanks!

like image 542
ihorko Avatar asked Apr 02 '11 09:04

ihorko


People also ask

How do I get tree structure data in SQL?

In the SQL tree structure, every node has its own, unique id. It has a reference to the parent node. For every node in a submenu we need its sequence number for ordering purposes. The name column is just a label which will be shown on the website.

What is query tree in SQL Server?

A query tree is a tree data structure representing a relational algebra expression. The tables of the query are represented as leaf nodes. The relational algebra operations are represented as the internal nodes. The root represents the query as a whole.


1 Answers

Expanding on a_horse_with_no_name's answer, this show how to use SQL Server's implementation of recursive CTE (recursive single-record cross apply) in combination with row_number() to produce the exact output in the question.

declare @t table(id int,parentId int,name varchar(20))
insert @t select 1,  0        ,'Category1'
insert @t select 2,  0,        'Category2'
insert @t select 3,  1,        'Category3'
insert @t select 4 , 2,        'Category4'
insert @t select 5 , 1,        'Category5'
insert @t select 6 , 2,        'Category6'
insert @t select 7 , 3,        'Category7'
;

WITH tree (id, parentid, level, name, rn) as 
(
   SELECT id, parentid, 0 as level, name,
       convert(varchar(max),right(row_number() over (order by id),10)) rn
   FROM @t
   WHERE parentid = 0

   UNION ALL

   SELECT c2.id, c2.parentid, tree.level + 1, c2.name,
       rn + '/' + convert(varchar(max),right(row_number() over (order by tree.id),10))
   FROM @t c2 
     INNER JOIN tree ON tree.id = c2.parentid
)
SELECT *
FROM tree
ORDER BY cast('/' + RN + '/' as hierarchyid)

To be honest, using the IDs themselves to produce the tree "path" would work, since we are ordering directly by id, but I thought I'd slip in the row_number() function.

like image 160
RichardTheKiwi Avatar answered Oct 14 '22 05:10

RichardTheKiwi