8

我有一个具有这种结构的 MySQL 数据库表:

table
    id INT NOT NULL PRIMARY KEY
    data ..
    next_id INT NULL

我需要按链表的顺序获取数据。例如,给定以下数据:

 id | next_id
----+---------
  1 |       2
  2 |       4
  3 |       9
  4 |       3
  9 |    NULL

我需要按顺序获取 id=1、2、4、3、9 的行。如何使用数据库查询来做到这一点?(我可以在客户端做到这一点。我很好奇这是否可以在数据库端完成。因此,说这是不可能的(有足够的证据))。

最好有一个终止点(例如,在 10 次获取后停止,或者当行上的某些条件变为真时),但这不是必需的(可以在客户端完成)。我(希望我)不需要检查循环引用。

4

3 回答 3

6

某些品牌的数据库(例如 Oracle、Microsoft SQL Server)支持额外的 SQL 语法来运行“递归查询”,但 MySQL 不支持任何此类解决方案。

您描述的问题与在 SQL 数据库中表示树结构相同。你只有一棵又长又瘦的树。

有几种解决方案可以从 RDBMS 中存储和获取这种数据结构。请参阅以下一些问题:


既然您提到您想限制查询返回的“深度”,您可以在以这种方式查询列表时实现这一点:

SELECT * FROM mytable t1
 LEFT JOIN mytable t2 ON (t1.next_id = t2.id)
 LEFT JOIN mytable t3 ON (t2.next_id = t3.id)
 LEFT JOIN mytable t4 ON (t3.next_id = t4.id)
 LEFT JOIN mytable t5 ON (t4.next_id = t5.id)
 LEFT JOIN mytable t6 ON (t5.next_id = t6.id)
 LEFT JOIN mytable t7 ON (t6.next_id = t7.id)
 LEFT JOIN mytable t8 ON (t7.next_id = t8.id)
 LEFT JOIN mytable t9 ON (t8.next_id = t9.id)
 LEFT JOIN mytable t10 ON (t9.next_id = t10.id);

它会像糖蜜一样执行,结果将全部返回一行(每个链表),但你会得到结果。

于 2009-03-23T20:49:55.330 回答
5

如果您要避免的是有多个查询(每个节点一个)并且您可以添加列,那么您可以有一个链接到根节点的新列。这样,您可以通过根 ID 一次提取所有数据,但您仍然必须在客户端对列表(或树)进行排序。

因此,在此示例中,您将拥有:

 id | next_id | root_id
----+---------+---------
  1 |       2 |       1
  2 |       4 |       1
  3 |       9 |       1
  4 |       3 |       1
  9 |    NULL |       1

当然,与传统的链表或树相比,这样做的缺点是根不能在不写入 O(n) 数量级的情况下更改,其中 n 是节点数。这是因为您必须更新每个节点的根 ID。幸运的是,除非您在中间划分列表/树,否则您应该始终能够在单个更新查询中执行此操作。

于 2010-08-31T18:46:59.873 回答
2

这与其说是一种解决方案,不如说是一种解决方法,但是对于线性列表(而不是 Bill Karwin 提到的树),在列表中使用排序列可能更有效。例如:

TABLE `schema`.`my_table` (
    `id` INT NOT NULL PRIMARY KEY,
    `order` INT,
    data ..,
    INDEX `ix_order` (`sort_order` ASC)
);

然后:

SELECT * FROM `schema`.`my_table` ORDER BY `order`;

这具有插入速度较慢的缺点(您必须将所有已排序的元素重新定位到插入点之后),但由于 order 列已编入索引,因此检索速度应该很快。

于 2010-08-13T16:17:45.587 回答