1

我的日期以树形结构组织。

以下适用(Oracle SQL 语法):

CREATE TABLE TREE
(
  NAME VARCHAR2(20),
  ID NUMBER(10, 0),
  PARENT NUMBER(10, 0)
)
;

INSERT INTO "TREE" (NAME, ID) VALUES ('a', '1');
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.1', '2', '1');
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.2', '3', '1');
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.2.1', '4', '3');
INSERT INTO "TREE" (NAME, ID, PARENT) VALUES ('a.2.2', '5', '3');
INSERT INTO "TREE" (NAME, ID) VALUES ('b', '6');

我想按 id 返回完整的树,所以对于查询:

select name, id <<<TODO LOGIC>> where id = 1

我会得到

|  name  |  id  |
|  a     |  1   |
|  a.1   |  2   |
|  a.2   |  3   |
|  a.2.1 |  4   |
|  a.2.2 |  5   |

对于子树,我会得到:

select name, id <<<TODO LOGIC>> where id = 3

我会得到

|  name  |  id  |
|  a.2   |  3   |
|  a.2.1 |  4   |
|  a.2.2 |  5   |

其中,对于平面条目 b,它将得到

select name, id <<<TODO LOGIC>> where id = 6

我会得到

|  name  |  id  |
|  b     |  6   |

似乎简单的遗漏连接查询无法实现此目的,还是我遗漏了什么?

以下查询确实返回了完整的结构,但是当开始使用where语句进行过滤时,它会失败。

select t1.id t1Id, t2.id t2Id, t1.name t1Name, t2.name t2Name from tree t1 left outer join tree t2 on t1.id = t2.parent
4

3 回答 3

3

当你有一个树结构时,你可能需要一个分层查询。这里是:

 select t.*
   from tree t
connect by prior t.id = t.parent
  start with t.id = :id
  order siblings by t.id

有关详细信息,请参阅分层查询

于 2009-11-23T11:44:42.770 回答
2

您可以在 Oracle 上使用 start with - connect by 语法。如果我没记错的话是这样的

select * from Tree t
start with t.ID = 1 connect by prior t.ID = t.Parent

但是我没有 Oracle 可以立即检查它。也许它的prior t.Parent = t.ID. 请注意,有时它可能会很慢,请谨慎使用。

另一种方法是创建表来存储节点之间的所有间接关系(不仅是 aa.1,还有 aa.2.1 等)。您可以使用 PL/SQL 递归存储过程来填充它。两种方式:

  1. 简单的方法是制作一个完全重新填充间接表的过程。您可以在运行报告之前调用它。

  2. 如果您需要即时效果,您应该编写 refill 程序,以便它只为树中的一条记录更新间接关系。然后,您禁止直接插入和更新 Tree,并强制它们通过存储的 PL/SQL 过程(如 InsertTree/UpdateTree),而后者又将调用过程来更新具有间接关系的表。

于 2009-11-23T11:07:10.697 回答
0

您可以使用union它,并且您需要限制树的深度以便可以在一个查询中选择它。

SELECT id, name
FROM TREE as node
WHERE 
  node.id = :id
UNION
SELECT child1.id, child1.name
FROM TREE as node
  inner join TREE as child1 on node.id = child1.parent
WHERE 
  node.id = :id
UNION
SELECT child2.id, child2.name
FROM TREE as node
  inner join TREE as child1 on node.id = child1.parent
  inner join TREE as child2 on child1.id = child2.parent
WHERE 
  node.id = :id

这里的问题是,SQL 在递归方面非常糟糕(而关系结构实际上在这方面很棒)。

要使其完全动态化,请对树中的每个级别使用查询,或者如果有任何可用的内容,请使用特定于数据库引擎的 SQL 扩展。

于 2009-11-23T11:02:02.923 回答