3

现在有一个问题,我们通常使用这种技术来维护父子关系,即我们将所有实体存储在一个带有parent_id列的表中,并且所有最顶层的父母在 parent_id 列中都有0这是我同意的一种很好的标准化技术,但是也有一个缺点,速度慢,效率低。这主要是由递归引起的,例如对于每个父级,我们必须一次又一次地运行查询以生成树

SELECT id FROM `table` WHERE parent_id=something

我已经查看了一些解决方案,有些人可能会尝试通过一次又一次地运行查询来使用任何编程语言来做到这一点,这会在服务器上产生负载,有些人提供了存储过程,但也涉及递归。

所以我的问题是我们可以用一个数据库查询树(连接或子查询)来做到这一点吗?

  • 如果我们知道深度还是不知道深度?

  • 如果可能的话,我们如何才能获得任何孩子的最高父母(即 parent_id=0)?

  • 如果不可能,那么为什么这种技术如此有名,而它有缺陷,或者我们有另一种解决方案?

    我已经添加了 sql fiddle,但它只有架构

小提琴

4

2 回答 2

3

我不知道 MYSQL 是否可行,在我的职业生涯中,我一直主要使用 SQL Server。在 SQL Server 中,使用该WITH语句只需 1 个查询即可完成此操作。

这演示了如何在所有级别获取对象 (id=3) 的所有子项

With pa as (
     select pa1.*
     From prarent as pa1
     Where id = 3
     union all
     select pa2.*
     from pa join prarent as pa2 on pa.id = pa2.parent_id
  )
select * from pa where pa.id != 3

演示

另一个让对象 (id=7) 的所有父级达到最高的示例

With pa as (
     select pa1.*
     From prarent as pa1
     Where id = 7
     union all
     select pa2.*
     from pa join prarent as pa2 on pa.parent_id = pa2.id
  )
select * from pa where pa.id != 7

演示

另一个仅获取最顶层父级的示例

With pa as (
     select pa1.*
     From prarent as pa1
     Where id = 7
     union all
     select pa2.*
     from pa join prarent as pa2 on pa.parent_id = pa2.id
  )
select top 1 * 
from pa 
where pa.id != 7
order by id asc

在此示例中,我假设 id 是递增的,并且我使用一种简单的方式(仅出于演示目的)来获取最顶层 using order by. 您可以根据您的数据库设计使用另一种技术。

演示

使用这种类似的技术,你可以做更多的事情,比如让最底层的孩子,....

于 2013-07-21T10:03:57.457 回答
1

如果您有很多关卡或大量数据,这将是不切实际的。

否则,您可以尝试模拟递归函数的作用。即使您不会获得相同的性能,如果您没有太多数据,也没有太多级别,这也没关系。

一般程序如下:

  1. 对于给定的父级,选择具有该 ID 的记录
  2. 此外,选择以它为 PARENT_ID 的记录,并将其与上一个 UNION
  3. 步骤 #2 中的子查询给出了第一级子查询,因此您可以编写一个查询来选择他们的 ID,并将其用作第三个查询中的子查询,即“where PARENT_ID IN (sub-select)”
  4. 这将类似于第 3 步,然后继续

它看起来像这样:(请参阅此处的小提琴

select *
from prarent P0
where id = 3

union 

select *
from prarent P1
where parent_id = 3

union 

select *
from prarent P2
where parent_id in
 (  select distinct id
    from prarent P1
    where p1.parent_id = 3
 )

union 

select *
from prarent P3
where parent_id in
 (  select distinct id
    from prarent P2
    where parent_id in
    (  select distinct id
       from prarent P1
       where p1.parent_id = 3
    )
 )
于 2013-07-16T18:59:37.007 回答