【问题标题】:PostgreSQL ltree find all ancestors of a given label (not path)PostgreSQL ltree 查找给定标签的所有祖先(不是路径)
【发布时间】:2015-01-24 15:24:58
【问题描述】:

我有一个带有 ltree 路径列的表。在我的层次结构中,标签的路径是唯一的,这意味着每个标签都只有一个父标签。换句话说,表中没有两条 ltree 路径会以相同的标签结尾。

我有一个 ltree 标签,比如说“C”。

我可以通过以下查询找到该标签的所有后代行:

select * from myTree where path ~ '*.C.*';

这可以正常工作并给出正确的子树。

现在我需要执行查询以查找此给定标签的所有祖先行。我的意思是,例如,如果表中有 3 行标签为“A”、“AB”、“ABC”,我想获取路径为“A”和“AB”的行(可能包括“ABC”本身,暂时无所谓)。

如果我知道“C”的完整路径(上例中的“A.B.C”),那么使用@> 运算符就可以轻松完成任务。但是,现在我只知道“C”,我仍然想通过单个查询来完成任务。有没有办法做到这一点?

【问题讨论】:

  • 我在ltree 中没有找到对此的直接支持,但是您可以使用path ~ '*.C' 选择子节点,然后您可以进行自连接以获取所有祖先。跨度>
  • 谢谢,我也去试试。
  • 你怎么知道“C”,但不知道完整路径“A.B.C”?他们不是在桌子的同一行吗?
  • @KouberSaparev 是的,但“C”是该行的一种全局标识符,在这种情况下我将其作为参数接收。
  • 然后通过子选择,您可以获得与标识符对应的路径并通过它进行搜索(如下面提出的答案)。

标签: sql postgresql ltree


【解决方案1】:

类似这样的:

WITH r AS
(
    SELECT *, row_number() OVER (ORDER BY path) rn
      FROM myTree
)
SELECT *
  FROM r
 WHERE rn <= (SELECT rn FROM r WHERE path ~ '*.C');

SQL Fiddle

也许有更好的方法使用内置的东西。

【讨论】:

  • 谢谢,就我目前的知识而言,这看起来很棘手,但会试一试。我害怕的是(我认为)我仅限于简单的查询语句,因为我在 ORM 库后面。
【解决方案2】:
SELECT
  *
FROM
  myTree
WHERE
  path @> (
    SELECT
      path
    FROM
      myTree
    WHERE
      label = 'C'
  );

【讨论】:

  • 耶稣这很简单。现在我坐在电脑前的时间太长了 :) 当我设法通过自连接实现它时,但这种情况下的子查询更具可读性。谢谢。
  • 感谢您的好回答!但是如果子选择返回不止一行呢?如果某个节点有多个父节点,则可能会发生这种情况。然后Postgres显示错误:“作为表达式的子查询返回的不止一行”有没有办法处理这个?
  • 如何使用 ltree 使用的物化路径模式定义具有多个父节点的节点?
  • 一个节点绝对有可能在一个 DAG 中有多个父节点。在那种情况下@Johnner,最好重写为 JOIN,而不是子查询: SELECT * FROM myTree JOIN myTree AS mt ON myTree.path @> mt.path AND mt.label = 'C';
猜你喜欢
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
相关资源
最近更新 更多