如何对包含子组的有序列表进行SQL查询?

时间:2010-10-05 17:03:55

标签: sql mysql hierarchical-data

我有一个具有这种结构的表

 id integer
  parent_id integer
  order_n integer
  info text

每行可以有一个父行(parent_id,如果没有父行,则为null)和一个插入顺序(order_n)。每次插入一行时,order_n字段将被设置为相关的“在他的父母内部”。因此,第一级的两行将是order_n = 1而order_b = 2.但是第一行“内部”的新行将是order_n = 1

实施例

  id    parent_id   order_n   info
  1     null        1         "Beatles"
  2     null        2         "Stones"
  3     1           1          "Paul"
  4     1           2          "John"
  5     2           1          "Mick"
  6     2           2          "Keith"

子级别是无限的。

我正在尝试做的事情(我悲惨地失败)是查询谁检索任何级别(包括第一级)的所有行,并根据他的order_n属性对其进行排序,但是对嵌套进行分组行。例如,在前面的示例中,我们需要以这种方式检索结果

1     null        1         "Beatles"
3     1           1          "Paul"
4     1           2          "John"
2     null        2         "Stones"
5     2           1          "Mick"
6     2           2          "Keith"

我正在努力尝试但我对SQL知之甚少,我会事先感谢你所有明智的建议。

我正在使用MySQL,但理想的是尝试“sql standard”

内在水平是无限的。

2 个答案:

答案 0 :(得分:1)

直到你的最后一行“内在水平是无限的”,这不是一个难以写的问题。您将为自己所需的每个级别加入表格。如果预定义的最大值为5级,则可以将表连接到自身5次(左连接)以实现此目的。

非常伪造的代码:

Select whatever
from mytable my1
left join mytable my2 on my1.id = my2.parent_id
where whatever
order by case when parent_id is null then id else parent_id end, 
case when parent_id  is null then 0 else order_n end

order by子句中的case语句旨在识别顶级父记录,并将其与其余记录分组。

想要更多级别?扩展join语句:     在my2.id = my3.parent_id上加入mytable my3     在my3.id = my4.parent_id上加入mytable my4     在my4.id = my5.parent_id

上加入mytable my5

没有'最大'数量的级别,根据马修PK的动态SQL是(据我所知)你唯一的追索权。

my1,my2,my3等也可能不是最简单的别名命名约定,选择你可以遵循的内容。

答案 1 :(得分:0)

这将是动态SQL,并且有点复杂。

我们需要更多细节来确定对此的帮助,但它将从以下开始:

您需要确定查询的深度行数,否则会冒无限循环的风险。

确定每行所需的列

基本上,您将在存储过程中创建一个varchar,它将根据您的查询需要增长。

您需要在此查询中将变量设置为最高的n顺序,然后循环,为每个嵌套表添加列,连接,顺序,组和(最重要的!)别名。

这是一些伪代码:

int maxval = 0
select maxval = max(n-level) from table where ...
string newalias = ""
string oldalias = newguid
int cnt = 0
int parentid = NULL

string selectstatement = "select "
string joinstatement = "from table as" oldalias
string orderstatement = "order by"

while cnt < maxval
    newalias = newguid

    selectstatement = selectstatement + "," + newalias + "." + columnnames
    joinstatement = joinstatement + " JOIN table as " + newalias + "on " + newalias + ".columnname = " + oldalias + ".columname"
    orderstatement = orderstatement + "," + newalias + ".columnname"
maxval = maxval + 1
oldalias= newalias
loop