【问题标题】:Postgres: Best way to query hierarchy structures by namePostgres:按名称查询层次结构的最佳方法
【发布时间】:2015-09-22 00:30:12
【问题描述】:

假设我有如下的类别层次结构:

id |     name   | parent_id
---+------------+-----------
 1 | Computers  |  
---+------------+-----------
 2 | Laptops    | 1
---+------------+-----------
 3 | Desktops   | 1
---+------------+-----------
 4 | Big        | 2
---+------------+-----------
 5 | Small      | 2
 ---+------------+-----------
 4 | Big        | 3
---+------------+-----------
 5 | Small      | 3

现在,假设有人给我输入['Computers', 'Laptops', 'Small']。在 Postgres 中查询层次结构并到达正确的最终类别(例如 id 5)的最佳方式是什么?

我知道您可以使用递归 CTE 来遍历树,但是将输入数组参数化到查询中的最佳方法是什么?

以下或多或少的工作,但感觉真的低于标准,因为你必须拆分参数数组:

WITH RECURSIVE path(n, id, name, parent_id) AS (
  SELECT 
    1, c.id, c.name, c.parent_id
  FROM 
    categories c
  WHERE c.name = 'Computers' AND parent_id IS NULL
  UNION ALL
  SELECT n+1, c.id, c.name, c.parent_id 
  FROM categories c,
    (SELECT * FROM unnest(ARRAY['Laptops', 'Small']) WITH ORDINALITY np(name, m)) np,
    path p
    WHERE c.parent_id = p.id AND np.m = n AND np.name = c.name
)
SELECT * FROM path;

【问题讨论】:

  • 这就是为什么我非常想念从 Oracle 到 postgresql 的 levelconnect by

标签: postgresql tree recursive-cte


【解决方案1】:

CTE 应如下所示:

WITH RECURSIVE search AS (
  SELECT ARRAY['Computers', 'Laptops', 'Small'] AS terms
), path (n, id, name, parent_id) AS (
  SELECT 1, id, name, parent_id
  FROM categories, search
  WHERE name = terms[1]
  UNION
  SELECT p.n+1, c.id, c.name, c.parent_id
  FROM categories c, path p, search s
  WHERE c.parent_id = p.id
    AND c.name = (s.terms)[p.n+1]
)
SELECT * FROM path;

巧妙的是,您只需指定一次数组,然后 CTE 的其他术语就可以简单地遍历数组,不管路径有多长。无需取消嵌套。请注意,这也适用于部分树:['Desktop', 'Big'] 将很好地生成正确的路径(显然不包括 'Computer')。

SQLFiddle here

【讨论】:

  • 谢谢!添加了AND parent_id IS NULL 以确保我们始终从根类别开始。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-24
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多