7

假设我有一张这样的桌子:

=================================
| ID |  Parent_ID | Page_Name   |
=================================
| 1  |  NULL      |  Home       |
| 2  |  NULL      |  Services   |
| 3  |  2         |  Baking     |
| 4  |  3         |  Cakes      |
| 5  |  3         |  Bread      |
| 6  |  5         |  Flat Bread |
---------------------------------

我怎样才能以这种格式实际订购结果?即由父级 -> 子级 -> 子级命令,基于我只需要说最多 5 个级别?我已经研究过“嵌套集模型”,但它似乎对我的要求来说太复杂了。我不确定的是真的理解一个 SQL 查询,我可以用它来显示上面的结果,或者在这种情况下,我应该使用像 PHP 这样的服务器端语言来为我做这件事吗?

4

2 回答 2

4

编辑

解决 Gordons 说明的工作样本

查询计算节点路径,因为您有固定的最大树深度,并按它排序。

SQL小提琴

MySQL 5.5.30 架构设置

create table mytable(id int, parent_id int, name varchar(100));

insert mytable(id, parent_id, name)
values (1, null, 'Home'),
(2, null, 'Services'),
(3, 2, 'Baking'),
(4, 3, 'Cakes'),
(5, 3, 'Bread'),
(6, 5, 'Flat Bread'),
(7, 1, 'Something');

查询 1

select t0.*,
  concat(
      case coalesce(t4.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t4.Parent_ID as char), '\\')
      end,
      case coalesce(t3.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t3.Parent_ID as char), '\\')
      end,
      case coalesce(t2.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t2.Parent_ID as char), '\\')
      end,
      case coalesce(t1.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t1.Parent_ID as char), '\\')
      end,
      case coalesce(t0.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t0.Parent_ID as char), '\\')
      end,
      cast(t0.id as char)
    ) as path
from mytable t0 
    left join mytable t1 on t0.Parent_ID = t1.Id
    left join mytable t2 on t1.Parent_ID = t2.Id
    left join mytable t3 on t2.Parent_ID = t3.Id
    left join mytable t4 on t3.Parent_ID = t4.Id
order by 
  concat(
      case coalesce(t4.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t4.Parent_ID as char), '\\')
      end,
      case coalesce(t3.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t3.Parent_ID as char), '\\')
      end,
      case coalesce(t2.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t2.Parent_ID as char), '\\')
      end,
      case coalesce(t1.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t1.Parent_ID as char), '\\')
      end,
      case coalesce(t0.Parent_ID, 0) 
        when 0 then ''
        else concat(cast(t0.Parent_ID as char), '\\')
      end,
      cast(t0.id as char)
    )

结果

| ID | PARENT_ID |       NAME |    PATH |
-----------------------------------------
|  1 |    (null) |       Home |       1 |
|  7 |         1 |  Something |     1\7 |
|  2 |    (null) |   Services |       2 |
|  3 |         2 |     Baking |     2\3 |
|  4 |         3 |      Cakes |   2\3\4 |
|  5 |         3 |      Bread |   2\3\5 |
|  6 |         5 | Flat Bread | 2\3\5\6 |
于 2013-04-23T14:32:50.713 回答
1

你可以试试这个:

select t.*,
       (case when t4.parent_id is not NULL then 5
             when t4.id is not null then 4
             when t3.id is not null then 3
             when t2.id is not null then 2
             when t1.id is not null then 1
             else 0
        end) as level
from t left outer join
     t t1
     on t.parent_id = t1.id left outer join
     t t2
     on t1.parent_id = t2.id left outer join
     t t3
     on t2.parent_id = t3.id left outer join
     t t4
     on t3.parent_id = t4.id
order by coalesce(t4.parent_id, t4.id, t3.id, t2.id, t1.id, t.id),
         coalesce(t4.id, t3.id, t2.id, t1.id, t.id),
         coalesce(t3.id, t2.id, t1.id, t.id),
         coalesce(t1.id, t.id),
         t.id

如果层次结构是有限的,则不需要递归查询。

order by 子句是棘手的部分。它只是按层次结构的级别排序,从最顶层开始。

原始版本适用于问题中的数据。更广泛的测试发现它并不总是有效。我相信这个版本总是有效的。

于 2013-04-23T14:27:48.750 回答