3

现在有一个问题,我们通常使用这种技术来维护父子关系,即我们将所有实体存储在一个表中,其中parent_id列为parent_id列,所有最顶级父母都有这是一个很好的和规范化技术我同意,但也有一个缺点,它是缓慢和低效率。这主要是由于像每个家长,我们必须再次运行查询,并再次作出树通过第n个孩子ID获得最顶级的父母?

SELECT id FROM `table` WHERE parent_id=something 

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

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

  • 如果我们知道深度还是我们不知道深度?
  • 如果有可能,我们如何获得任何孩子的最顶级父母(即parent_id = 0)?
  • 如果这是不可能的,那么为什么这种技术是如此着名,虽然它有缺陷,或者我们有另一种解决方案呢?

    我已经加入了SQL小提琴,但它只有架构

FIDDLE

+3

不像一些其他的RDBMS,MySQL不支持递归函数等是不适合这是存储分层数据的“邻接表”模型。您应该考虑重新构建您的模式以将分层结构嵌入到MySQL可以利用的表单中,例如“嵌套集合”或“传递闭包”。 – eggyal

+0

@eggyal但现在很多cms都遵循这种技术,像最常用的wordpress也提供了第n个菜单级别,页面级别和类别级别,所以我的问题是有没有更好的方式来存储和获取树,而无需运行多个查询? –

+0

您可以为您希望获取的每一代自行加入,但深度总是受限于查询中的连接数。 – eggyal

回答

3

我不知道是否有可能与MYSQL,我一直在工作主要是与SQL Server在我的职业生涯。在SQL Server中,可以通过使用WITH语句只用1个查询来完成。

这演示了如何在各级

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 

DEMO

又如得到一个对象(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 

DEMO

Anothe R实施例,仅保留最顶层父

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是增量和我用一个简单的方法(只用于演示目的)使用order by以获得最顶层。您可以根据数据库设计使用其他技术。

DEMO

使用这种类似的技术,你可以做更多,喜欢把自己的最底部孩子,....

+0

非常感谢你,如果你知道这种功能可能在MySQL中,那么请编辑这个答案,这里是你的奖励:) –

+0

@dianuj:非常感谢你 –

0

如果你有很多的层次,或者大量数据,这将是不切实际的。

否则,您可以尝试模拟递归函数的功能。即使你不会得到相同的表现,如果你没有太多的数据,也没有太多的水平,这并不重要。

的一般过程是如下:

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

它看起来是这样的:(see the Fiddle here

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 
    ) 
) 
+0

如果你看到你有深度1联合查询与sub选择,你已经在你的答案中提到**如果你有很多的水平,或大量的数据,这将是不切实际的**我想要一个通用的如果不是,那么为什么这种方法如此受欢迎? –

+0

如果逻辑结构是一棵树,那么很少有替代品仍然是灵活的。实际上,当我使用“BOM”结构时,用例就是这样一个用例,它关注于一定的层次,并在需要时进行深入研究。所以,实际上,即使数据库没有提供容易递归的SQL,我也可能保持这种结构。如果您有能力将SQL与某些3-G代码混合使用(即使它存储在存储过程中),但在大多数情况下,性能并不是很重要的问题。编码麻烦,但不是性能问题。 –

相关问题