简体   繁体   English

递归查询SQL Server

[英]Recursive Query SQL Server

I'm stuck on this problem for a while now. 我在这个问题上停留了一段时间。

I've got one table called Category which looks like this: 我有一张名为Category的表,看起来像这样:

number, name, parent
1     , Fruit, null
2     , Apples, 1
3     , Golden Apples, 2
4     , Pineapples, 1

Now, how am I supposed to select the main category and with its sub categories and if they exist, their sub categories. 现在,我应该如何选择主要类别及其子类别,如果存在,还应选择其子类别。

I have to output it in PHP like this: 我必须像这样在PHP中输出它:

<div>Fruit
     <div>Apples
          <div>Golden Apples</div>
     </div>
     <div>Pineapples</div>
</div>

In theory there is no known end or amount of sub categories you can have. 从理论上讲,您无法知道子类别的末尾或数量。 I've struggled with this problem for a while. 我已经为这个问题苦苦挣扎了一段时间。

It is possible to do this with a loop and then run a query to select its sub categories again however this will be very resource intensive on the database side. 可以通过循环执行此操作,然后再次运行查询以选择其子类别,但是这在数据库方面会占用大量资源。

I hope someone can help me with this one. 我希望有人可以帮助我。

The ideal approach is to normalize your data. 理想的方法是规范化数据。 Have a table for categories and a table that holds the members of each category. 有一个类别表和一个表,其中包含每个类别的成员。 Then you can do a simple left join between the tables to get what you are looking for. 然后,您可以在表之间进行简单的左连接以获取所需的内容。 Since you do not have that, you will need to select from the main table and then do a left join on the same table using aliases. 由于您没有该名称,因此需要从主表中进行选择,然后使用别名对同一表进行左连接。

Something like this will work. 这样的事情会起作用。

select number,name from Category where Parent is NULL Left Join Category as Items on Items.Parent = Category.number 选择号码,从类别名称,其中母公司为NULL左连接类别的Items上Items.Parent = Category.number

try using a recursive CTE like this: 尝试使用像这样的递归CTE:

--this is just an old example I've used before, but it kind of matches your table
--go through a nested table supervisor - user table and display the chain
DECLARE @Contacts table (id int, first_name varchar(10), reports_to_id int)
INSERT @Contacts VALUES (1,'Jerome', NULL )  -- tree is as follows:
INSERT @Contacts VALUES (2,'Joe'   ,'1')     --                      1-Jerome
INSERT @Contacts VALUES (3,'Paul'  ,'2')     --                     /        \
INSERT @Contacts VALUES (4,'Jack'  ,'3')     --              2-Joe           9-Bill
INSERT @Contacts VALUES (5,'Daniel','3')     --            /       \              \
INSERT @Contacts VALUES (6,'David' ,'2')     --     3-Paul          6-David       10-Sam
INSERT @Contacts VALUES (7,'Ian'   ,'6')     --    /      \            /    \
INSERT @Contacts VALUES (8,'Helen' ,'6')     -- 4-Jack  5-Daniel   7-Ian    8-Helen
INSERT @Contacts VALUES (9,'Bill ' ,'1')     --
INSERT @Contacts VALUES (10,'Sam'  ,'9')     --

DECLARE @Root_id  int

--get complete tree---------------------------------------------------
SET @Root_id=null
PRINT '@Root_id='+COALESCE(''''+CONVERT(varchar(5),@Root_id)+'''','null')
;WITH StaffTree AS
(
    SELECT 
        c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf
        FROM @Contacts                  c
            LEFT OUTER JOIN @Contacts  cc ON c.reports_to_id=cc.id
        WHERE c.id=@Root_id OR (@Root_id IS NULL AND c.reports_to_id IS NULL)
    UNION ALL
        SELECT 
            s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1
        FROM StaffTree            t
            INNER JOIN @Contacts  s ON t.id=s.reports_to_id
    WHERE s.reports_to_id=@Root_id OR @Root_id IS NULL OR t.LevelOf>1
)
SELECT * FROM StaffTree ORDER BY LevelOf,first_name

OUTPUT: OUTPUT:

@Root_id=null
         id first_name reports_to_id  Manager_id Manager_first_name     LevelOf
----------- ---------- ------------- ----------- ------------------ -----------
          1 Jerome              NULL        NULL NULL                         1
          9 Bill                   1           1 Jerome                       2
          2 Joe                    1           1 Jerome                       2
          6 David                  2           2 Joe                          3
          3 Paul                   2           2 Joe                          3
         10 Sam                    9           9 Bill                         3
          5 Daniel                 3           3 Paul                         4
          8 Helen                  6           6 David                        4
          7 Ian                    6           6 David                        4
          4 Jack                   3           3 Paul                         4

(10 row(s) affected)

I would think you could loop over the result set in PHP and build your DIVs. 我认为您可以遍历PHP中的结果集并构建DIV。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM