2009-11-06 64 views
3

我已經MySQL表定義爲:MySQL的:獲取所有子類,子孫

類:CATEGORY_ID,CATEGORY_NAME,parent_category_id

我正在尋找一個很好的SQL查詢將檢索給定的所有後代CATEGORY_ID。這意味着,它的孩子和孩子的孩子。

如果有幫助,我們可以假設最高級別(3)。這個查詢可以在任何級別發送(根,級別2,級別3)。

謝謝!

Nathan

回答

5

有幾種方法可以將樹存儲在數據庫中。有一個關於sitepoint一個夢幻般的文章描述的所有技術:

http://articles.sitepoint.com/article/hierarchical-data-database/2

的一個,如果你希望能夠得到一棵樹的整個部分在一個查詢修改預購樹的遍歷這是最合適的。

這種技術也被稱爲嵌套集。這裏還有更多的信息,如果你想了解某個主題的文獻:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

+0

如何使用現有的結構? – 2009-11-06 22:23:58

+0

使用您當前的表結構,您必須使用遞歸查詢。 – jonnii 2009-11-06 22:25:56

0

MySQL不支持遞歸查詢,但可以使用while循環存儲過程中發現的所有後代。請參閱此book sampleThe edge list部分。

1

如果你想用這個結構,最大3級就可以加入表本身三次:

SELECT 
    c1.id AS level_1, 
    c2.id AS level_2, 
    c3.id AS level_3 
FROM categories c1 
LEFT JOIN categories c2 ON c1.id = c2.parent_id 
LEFT JOIN categories c3 ON c2.id = c3.parent_id 
WHERE c1.parent_id IS NULL 

我假定,父類有PARENT_ID NULL。

一些示例:

DECLARE @categories TABLE 
(
    id INT, 
    parent_id INT 
) 

INSERT INTO @categories(id,parent_id) VALUES(1,NULL) 
INSERT INTO @categories(id,parent_id) VALUES(4,1) 
INSERT INTO @categories(id,parent_id) VALUES(5,1) 
INSERT INTO @categories(id,parent_id) VALUES(6,5) 
INSERT INTO @categories(id,parent_id) VALUES(2,NULL) 

SELECT * FROM @categories 

SELECT c1.id AS level_1, c2.id AS level_2, 
    c3.id AS level_3 
FROM @categories c1 
LEFT JOIN @categories c2 ON c1.id = c2.parent_id 
LEFT JOIN @categories c3 ON c2.id = c3.parent_id 
WHERE c1.parent_id IS NULL 

返回:

level_1 | level_2 | level_3 
--------------------------- 
1  | 4  | NULL 
1  | 5  | 6 
2  | NULL | NULL 
+0

我喜歡你在這裏得到的地方,除了結尾格式不是很容易使用(這個整個查詢然後被用作子查詢,例如WHERE categoryId IN(調用後裔列表) 我們是否可以創建一個查詢來生成一個緩存表,該列將包含parent_category_id,descendant。它會列出每個給定類別的所有後代? – 2009-11-06 22:59:06

+0

這不是一個解決方案,只是一個補丁,通常情況下我們無法預測類別級別。而且,至少,硬編碼是非常糟糕的。 – Lambrusco 2016-11-30 08:40:59

+1

@Lambrusco在答案7年後。謹慎給予適當的解決方案? – 2016-11-30 09:56:22

2

它可以在一個單一的查詢和一塊遞歸後端代碼邏輯來完成:Formatting a multi-level menu using only one query

如果你也做PHP,這篇文章附帶PHP作爲獎金的例子,但翻譯到另一種語言並不困難。由於您沒有提及您使用的服務器端語言,因此我無法給出任何提示。

希望這會有所幫助。