2012-07-12 54 views
6

我正在處理類別管理。我在哪裏有每行parentId。分類可以是n級的。 我可以遞歸調用PHP函數,它將返回類別樹數組。返回類別樹的Mysql查詢

enter image description here

現在的問題是:在管理面板,我想類別清單頁面,如下圖所示。即哪個類別在哪個類別下。

  • 首頁
  • 產品(編輯)(刪除)
  • 產品>產品1(編輯)(刪除)
  • 產品>產品2(編輯)(刪除)
  • 產品>產品2 >產品2 1(編輯)(刪除)
  • 產品>產品2>產品2 2(編輯)(刪除)
  • 與我們聯繫(編輯)(刪除)

我想要mysql查詢結果的順序如上所示。我不知道我怎麼能實現它。

SELECT * 
FROM tbl_categories 
ORDER BY ??? 

請指導。

+0

更好地利用它的服務器pgoramming語言。 – Oyeme 2012-07-12 09:20:09

+0

它正在編程。在列表中可以分頁,我想對該查詢使用限制。在我看到的購物車開源中的某處,但我不記得他們是如何完成的。 – VibhaJ 2012-07-12 09:23:43

+0

請向我們展示表結構,也就是說,我想要2獲得行產品2.1 – 2012-07-12 09:23:46

回答

0

在單個mysql查詢中無法實現此目的。 你可以通過執行多個查詢來實現這一點。 算法如下: 最初通過從數據庫中提取數據來創建一個數據集對象,您將填充它。 創建一個方法,該方法將父ID作爲參數,並返回其子節點(如果存在),並返回-1(如果沒有子節點)。 第一步:獲取所有沒有父(根)節點的行。步驟2: 迭代通過此結果。 例如,如果prod1和prod2是結果集中的初始返回節點。迭代這個RS我們得到了prod1,並且在我們的DataSET obj中插入了一行。然後我們發送prod1的id到獲取CHILD方法,獲取它的子元素,然後我們再次返回返回的結果集,並再次調用getCHILD方法,直到我們沒有得到最低節點。

2

有沒有單個SQL查詢那可以把你的結果按你預期的方式排序,基於這個表結構。

有解決這個問題的方法有兩種:

  1. 使用外部應用程序邏輯(DB外)進行遞歸調用,將發現每個類別的兒童和構建樹的應用。

  2. 使用在關係數據庫中存儲樹數據的算法之一。 其中一種算法被稱爲Modified Preorder Tree Traversal或簡稱爲MPTT。

假設我們使用的列lftrgt保持在遍歷左/右索引,當你插入一個新的類別,你將需要:

  1. 獲取父類信息通過編號:SELECT lft,rgt FROM tbl_categories WHERE categoryId=5 讓我們假設一個例子,父類別有lft=7rgt=10(在這種情況下,它已經有一個孩子)

  2. M AKE空間的新條目 - 2(1 LFT和1 RGT)轉移的所有記錄:

    UPDATE tbl_categories SET rgt=rgt+2 WHERE rgt>=10 ORDER BY rgt DESC

    UPDATE tbl_categories SET lft=lft+2 WHERE lft>=10 ORDER BY lft DESC

注意這裏ORDER下降。由於lftrgt應該是唯一的,因此建議對它們設置一個UNIQUE約束,然後在更新時降序以防止重複鍵錯誤。

  1. lft=<former parent rgt>rgt=<former parent rgt +1>並插入一個新的記錄...

    INSERT INTO tbl_categories SET categoryName="New Child",parentCategoryId=5,lft=11,rgt=12,...

你可以找到的代碼更詳細的例子,如果你搜索MPTT PHP MySQL。關於這個主題有不少教程。

+0

謝謝..檢查它.. – VibhaJ 2012-07-12 10:03:17

+3

@VibhaJ:另一種選擇將是一個封閉表:http://karwin.blogspot.de/2010/03/rendering-trees-with-closure-tables.html它具有額外的好處您可以使用外鍵來確保父類別實際存在。 – 2012-07-12 10:09:37

+0

順便說一句,我通常使用MPTT,同時仍然保留父母(我甚至增加深度)在表中,那麼它沒有尋找直接親屬的陷阱... – poncha 2012-07-12 10:34:59

2

您可以使用一個存儲的函數,它將遞歸地獲取根路徑並與您的父級連接。

DELIMITER $$ 
DROP FUNCTION IF EXISTS `get_category`$$ 
CREATE FUNCTION `get_category`(cat_id int) RETURNS VARCHAR(255) 
READS SQL DATA 
BEGIN 
DECLARE c_id INT; 
DECLARE p_id INT; 
DECLARE count INT; 
DECLARE cat_name VARCHAR(255); 
DECLARE cat_path VARCHAR(255); 
set c_id = cat_id; 
SELECT parent_category_id, category_name INTO p_id, cat_name FROM categories WHERE category_id = c_id; 
set c_id = p_id; 
set cat_path=cat_name; 
set count=0; 
WHILE (c_id IS NOT NULL) DO 

SELECT parent_category_id, category_name INTO p_id, cat_name FROM categories WHERE category_id = c_id; 
set c_id = p_id; 
set cat_path = concat_ws('>',cat_name,cat_path); 
set count = count + 1; 
IF count=10 THEN 
    SET c_id = NULL; 
END IF; 
END WHILE; 
RETURN cat_path; 
END 
$$ 
DELIMITER ; 

,然後調用這個函數我已經做了全面的檢查,以避免無限循環使用

select getcategory(category_id); 

Herre ..

+1

雖然這發現了單個類別的路徑,所以如果你正在讀取一棵樹,就需要爲每一個結果調用它......但不管怎樣;) – poncha 2012-07-12 10:12:29

+0

它只是一個原型,你甚至可以用一個遊標修改一個過程,並且循環到每個類別樹..繼續..我相信它可以完成 – satdev86 2012-07-12 10:18:43