我需要多少个SQL查询?

时间:2009-08-26 15:29:13

标签: sql database sqlite

我有一个数据库表(sqlite),其中包含构成树层次结构的项目。每个项目的父级都有一个 id 字段(对于自身)和 parentId 。现在给出一个项目,我必须检索从根到项目的整个链。

基本上伪代码的算法如下:

  1. 光标是项目
  2. 通过parentId检索游标的parentItem
  3. 如果parentItem不是rootItem,则cursor = parentItem并转到2。
  4. 所以我必须为每个项目执行SQL SELECT查询。

    是否可以检索整个链rootItem - > ... - > item只执行一次SQL查询?

3 个答案:

答案 0 :(得分:2)

有很多创造性的方法可以在数据库中组织层次结构数据,但我始终认为最简单的方式是以非分层格式恢复数据,然后以编程方式匹配父记录和子记录。

总工作量:1个查询+ 1个程序化传递数据集以创建层次结构。


替代方法:

我过去曾使用过这种方法,但收效甚微。您可以使用varchar(max)列存储树中每个项目的路径,如下所示:

ID    ParentID    Path
--    --------    ----
1     null        1/
2     1           1/2/
3     null        3/
4     2           1/2/4/
5     4           1/2/4/5/
6     null        6/
7     5           1/2/4/5/7/
9     5           1/2/4/5/9/

从那时起,获取ID = 5下的所有节点非常简单:

SELECT *
FROM table
WHERE Path like (SELECT Path FROM Table WHERE ID = 5) + '%'

答案 1 :(得分:0)

不是ANSI标准SQL,不是,不是。嗯,这不完全正确。你可以做左外连接并放入足以覆盖可能的最大深度,但除非你限制最大深度并包括那么多连接,否则它不会一直有效。

如果您的行集足够小(比如小于1000),则只需检索它们然后计算出来。它很可能比单次读取遍历更快。

您可以批处理父遍历。有一个像这样的查询:

SELECT t1.id id1, t1.parent parent1,
       t2.id id2, t2.parent parent2,
       t3.id id3, t3.parent parent3,
       t4.id id4, t4.parent parent4,
       t5.id id5, t5.parent parent5
FROM mytable t1
LEFT OUTER JOIN mytable t2 ON t1.parent = t2.id
LEFT OUTER JOIN mytable t3 ON t2.parent = t3.id
LEFT OUTER JOIN mytable t4 ON t3.parent = t4.id
LEFT OUTER JOIN mytable t5 ON t4.parent = t5.id
WHERE t1.id = 1234

并将其扩展为您想要的任何数字。如果最后检索的父项不为null,则您不在树的顶部,因此请再次运行查询。这样你就可以将它减少到1-2次往返。

除此之外,您可以查看在ID中编码该数据的方法。建议不要这样做,但如果您将每个节点限制为有100个孩子,则可以说ID为10030711的节点的路径为10 - > 03 - > 07 - > 11.那当然还有其他问题(比如最大ID长度),当然还有hacky。

值得注意的是,SQL中的分层数据有两种基本模型。邻接列表和嵌套集。你的方式(很常见)是一个邻接集。虽然嵌套集对这种情况没有帮助,但是插入它们很复杂。

答案 2 :(得分:0)

你能改变表结构吗?看起来存储左右节点比仅存储父节点更容易,因为这样就可以进行单个选择。请参阅以下链接:

http://www.mail-archive.com/sqlite-users@sqlite.org/msg23867.html

http://weblogs.asp.net/aghausman/archive/2009/03/16/storing-retrieving-hierarchical-data-in-sql-server-database.aspx(这是SQLServer,但它们有一个可能有用的图表。)

相关问题