2017-08-31 45 views
0

我知道您可以使用遞歸CTE獲取麪包屑/樹的路徑,但可以選擇知道麪包屑/樹的項嗎?從breadcrumb /樹路徑(Adjacency模型)獲取項目

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

例如,如果麪包屑是這樣的:A/B/C/B,我如何能夠返回ID爲3知道了這個信息的行?

+0

搜索麪包屑的最後部分(只有名稱是唯一的)? 'SELECT * FROM tab where name =(某些sql字符串func得到最後一部分)' – lad2025

+0

不幸的是名字不是唯一的。只有主鍵ID是 – jouerai

回答

1

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中,除非您希望它停在最接近的匹配處,並在找不到路徑時將其返回,在這種情況下,您需要取最後一行。

有趣的是,應該可以在MySQL中使用會話變量將parent_id從一行傳送到下一個,儘管MySQL沒有數組,但是可以使用find_in_set()來代替......一種黑客...