从breadcrumb / tree path获取项目(Adjacency model)

时间:2017-08-31 17:11:22

标签: mysql sql postgresql

我知道你可以使用递归CTE获取面包屑/树路径,但是是否可以选择知道面包屑/树的项目?

id| name | parent_id
--------------------
0 | a    | null
1 | b    | 0
2 | c    | 1
3 | b    | 2

例如,如果面包屑看起来像这样:a / b / c / b,我怎么能够知道这个信息返回id为3的行?

1 个答案:

答案 0 :(得分:2)

Postgres只是摇滚。

http://sqlfiddle.com/#!17/0a6f4/27

这个想法是构建教科书递归查询,它返回树中每个元素的路径,以及"等级"表示从根节点的数量。你也可以称之为"深度"。

然后,我们转过路径' a / b / c / b'进入ARRAY [' a'' b',' c'' b'] ...因此在[level]上索引此数组]给出了我们在每个级别寻找的节点的名称。

WITH RECURSIVE h(id,name,parent_id,level,path,search_path) AS (
  SELECT  id,
      name,
      parent_id,
      1,
      ARRAY[name],
      ARRAY['a','b','c','b']
    FROM t WHERE parent_id IS NULL AND name = 'a'
  UNION ALL
    SELECT   t.id,
         t.name,
         t.parent_id,
         level+1,
         path || t.name,
         h.search_path
    FROM t JOIN h ON(t.parent_id=h.id)
      WHERE search_path[level+1] = t.name
)
SELECT *, path=search_path as match FROM h;

按路径顺序从请求的路径返回节点。我添加了一个"匹配"在找到请求的行时变为true的列。如果您只想要这一行,请将条件放在where中,除非您希望它停在最接近的匹配处并返回它以防路径未找到,在这种情况下您需要取最后一行。

有趣的是,通过使用会话变量将parent_id从一行传输到下一行,应该可以在MySQL中尝试这一点,尽管MySQL没有数组,所以像find_in_set()这样的东西可以工作......会很友善一个黑客...