2010-09-27 47 views
2

我試圖來管理節點的檢索在nested set model表,而不是通過唯一的ID,但通過名稱(串),和不同父母下的樹內的其他節點可以被調用相同的方式。選擇在嵌套集模型的節點通過未唯一的名稱

至於現在,我使用的唯一的ID來獲得嵌套組內的節點:

SELECT 
    node.name, node.lft, node.rgt 
FROM tbl AS parent, tbl AS node 
WHERE node.lft BETWEEN parent.lft AND parent.rgt 
AND node.id = '{$node_id}' 
GROUP BY node.id

嘗試此方法擴展到更一般的方法來檢索通過其名稱的節點,我想出了含有多達HAVING子句爲節點的深度查詢檢索,檢查節點名稱和它的深度:

SELECT 
    node.name, node.lft, node.rgt, COUNT(node.id) AS depth 
FROM tbl AS parent, tbl AS node 
WHERE node.lft BETWEEN parent.lft AND parent.rgt 
GROUP BY node.id 
HAVING 
    (node.name = 'myParentName' AND depth = 1) 
    OR 
    (node.name = 'myParent2Name' AND depth = 2) 
    OR 
    ... 
# and so on 

但它並非十全十美:具有相同的名稱和相同深度的兩個節點,但是在不同的父母身上,無論是否等級高,都可以被檢索出來他們屬於。

實施例:

 
ARTICLES 
    | 
    +--PHP 
    | +--the-origins 
    | +--syntax 
    +--JS 
     +--history 
     +--syntax 

在這種情況下,上面的查詢將返回任一文章/ PHP /語法或製品/ JS /語法:具有深度3,事實上一「語法」節點,或者是下PHP節點或JS節點下。 有沒有一條有效的路徑來解決這個問題?

+0

因此,您正在輸入例如'PHP'和'語法'及其各自的深度,並且您希望他們的路徑位於頂部?或者,如果情況並非如此,那麼您需要什麼確切的輸入和輸出? – Wrikken 2010-09-27 20:06:55

+0

是的Wrikken,我正在努力做到這一點。我會從給定的路徑深度。 – 2010-09-27 21:11:11

回答

3

我不太確定你要在這裏做什麼。您是否試圖訪問路徑名爲ARTICLES/PHP/syntax的節點?如果是這樣你需要做的將是每個父母級別自聯接:

SELECT n0.* 
FROM tbl AS n0 
JOIN tbl AS n1 ON n0.lft BETWEEN n1.lft+1 AND n1.rgt 
JOIN tbl AS n2 ON n1.lft BETWEEN n2.lft+1 AND n2.rgt 
WHERE n0.name='syntax' AND n1.name='PHP' AND n2.name='ARTICLES' 

ETA重新註釋:做直子在嵌套組比賽是不是很有趣。您必須嘗試在每個連接的行之間選擇一箇中間父行。這是你不想存在的行,所以你然後用空的左連接反轉這個條件。例如:

SELECT n0.* 
FROM tbl AS n0 
JOIN tbl AS n1 ON n0.lft BETWEEN n1.lft+1 AND n1.rgt 
JOIN tbl AS n2 ON n1.lft BETWEEN n2.lft+1 AND n2.rgt 
LEFT JOIN tbl AS nn1 ON nn1.lft BETWEEN n1.lft+1 AND n0.lft-1 
LEFT JOIN tbl AS nn2 ON nn2.lft BETWEEN n2.lft+1 AND n1.lft-1 
WHERE nn1.lft IS NULL AND nn2.lft IS NULL 
AND n0.name='syntax' AND n1.name='PHP' AND n2.name='ARTICLES' 
+0

感謝bobince:這個方法(每個級別的漸進式JOINs)與adjacendy模型中使用的相同,所以嵌套集合模型在檢索任務中也顯示出一些限制,是不是? – 2010-09-27 21:11:45

+0

是的,嵌套集合在這裏並沒有給你帶來任何好處。嵌套集讓您能夠選擇滿足某些層次關係的行數;在這裏,你只想選擇一行,所以沒有優勢。嵌套集合的操作對於完成上面的查詢以獲得目標節點的'lft'將是理想的 - 將獲得該節點的所有祖先,這將是'SELECT * FROM tbl WHERE(節點的lft值)BETWEEN lft和rgt'。 – bobince 2010-09-27 21:54:36

+0

可能我解釋得不好我的任務,但我也需要一個節點及其整個層次結構。當然,我正在使用嵌套集合來利用這種技術帶來的特定優勢:通過它,我爲每個任務(例如getParents(),getChildren(),getSiblings())編寫了適當的分層方法。由給定的ID來執行它不是問題,因爲它是唯一的標識符,但我希望將檢索任務擴展到名稱。獲得父母(所請求元素的整個層次結構)正是我想要做的。 – 2010-09-29 10:40:23

相關問題