2009-08-15 68 views
3

我有我的數據庫頁表,每個頁面可以有如下父:MySQL查詢由家長命令,然後孩子放在

id   parent_id   title 
1    0     Home 
2    0     Sitemap 
3    0     Products 
4    3     Product 1 
5    3     Product 2 
6    4     Product 1 Review Page 

什麼是最好的MySQL查詢選擇下令所有頁面如果有多於一個等級,那麼由父母再兒童再再等一次,最多會有三個等級。上面的例子會產生所需的順序:

Home 
Sitemap 
Products 
    Product 1 
     Product 1 Review Page 
    Product 2 

回答

5

我想你應該多一個字段,你的表,稱爲水平和存儲在其中的節點的級別,然後排序您的級別查詢然後通過家長。

1

呃。像這樣的涉及樹的查詢很煩人,一般來說,如果你希望它可以擴展到任何級別,你不會用一個查詢來完成它,你會在每個級別上使用一些構建樹。

0

那麼,你總是可以在一個查詢中得到它,並在PHP中處理它。這可能是獲得樹的最簡單的方法。

+0

PHP是不夠快如SQL! – 2018-03-06 14:38:45

5

如果你必須堅持你的模型,我建議這個查詢:

SELECT p.id, p.title, 
     (
     SELECT LPAD(parent.id, 5, '0') 
     FROM page parent 
     WHERE parent.id = p.id AND parent.parent_id = 0 

     UNION 

     SELECT CONCAT(LPAD(parent.id, 5, '0'), '.', LPAD(child.id, 5, '0')) 
     FROM page parent 
     INNER JOIN page child ON (parent.id = child.parent_id) 
     WHERE child.id = p.id AND parent.parent_id = 0 

     UNION 

     SELECT CONCAT(LPAD(parent.id, 5, '0'), '.', LPAD(child.id, 5, '0'), '.', LPAD(grandchild.id, 5, '0')) 
     FROM page parent 
     INNER JOIN page child ON (parent.id = child.parent_id) 
     INNER JOIN page grandchild ON (child.id = grandchild.parent_id) 
     WHERE grandchild.id = p.id AND parent.parent_id = 0 
     ) AS level 
FROM page p 
ORDER BY level; 

結果集的例子:

+-----+-------------------------+-------------------+ 
| id | title     | level    | 
+-----+-------------------------+-------------------+ 
| 1 | Home     | 00001    | 
| 2 | Sitemap     | 00002    | 
| 3 | Products    | 00003    | 
| 4 | Product 1    | 00003.00004  | 
| 6 | Product 1 Review Page 1 | 00003.00004.00006 | 
| 646 | Product 1 Review Page 2 | 00003.00004.00646 | 
| 5 | Product 2    | 00003.00005  | 
| 644 | Product 3    | 00003.00644  | 
| 645 | Product 4    | 00003.00645  | 
+-----+-------------------------+-------------------+ 
9 rows in set (0.01 sec) 

的輸出講解:

+------+--------------------+--------------+--------+---------------+---------+---------+--------------------------+------+----------------+ 
| id | select_type  | table  | type | possible_keys | key  | key_len | ref      | rows | Extra   | 
+------+--------------------+--------------+--------+---------------+---------+---------+--------------------------+------+----------------+ 
| 1 | PRIMARY   | p   | ALL | NULL   | NULL | NULL | NULL      | 441 | Using filesort | 
| 2 | DEPENDENT SUBQUERY | parent  | eq_ref | PRIMARY,idx1 | PRIMARY | 4  | tmp.p.id     | 1 | Using where | 
| 3 | DEPENDENT UNION | child  | eq_ref | PRIMARY,idx1 | PRIMARY | 4  | tmp.p.id     | 1 |    | 
| 3 | DEPENDENT UNION | parent  | eq_ref | PRIMARY,idx1 | PRIMARY | 4  | tmp.child.parent_id  | 1 | Using where | 
| 4 | DEPENDENT UNION | grandchild | eq_ref | PRIMARY,idx1 | PRIMARY | 4  | tmp.p.id     | 1 |    | 
| 4 | DEPENDENT UNION | child  | eq_ref | PRIMARY,idx1 | PRIMARY | 4  | tmp.grandchild.parent_id | 1 |    | 
| 4 | DEPENDENT UNION | parent  | eq_ref | PRIMARY,idx1 | PRIMARY | 4  | tmp.child.parent_id  | 1 | Using where | 
| NULL | UNION RESULT  | <union2,3,4> | ALL | NULL   | NULL | NULL | NULL      | NULL |    | 
+------+--------------------+--------------+--------+---------------+---------+---------+--------------------------+------+----------------+ 
8 rows in set (0.00 sec) 

我用此表佈局:

CREATE TABLE `page` (
    `id` int(11) NOT NULL, 
    `parent_id` int(11) NOT NULL, 
    `title` varchar(255) default NULL, 
    PRIMARY KEY (`id`), 
    KEY `idx1` (`parent_id`) 
); 

請注意,我在parent_id中包含一個索引以提高性能。

+0

這是一個很好的答案。確實非常有用,只是在我的一個項目中使用了這種方法。謝謝。 – 2013-05-10 09:33:11

+0

這隻適用於3級,即直到孫子,在它下面顯示爲零級 – Shahbaz 2016-07-15 10:16:04

2

工作更聰明而不是更辛苦:

SELECT menu_name , CONCAT_WS('_', level3, level2, level1) as level FROM (SELECT 
t1.menu_name as menu_name , 
t3.sorting AS level3, 
t2.sorting AS level2, 
t1.sorting AS level1 
FROM 
en_menu_items as t1 
LEFT JOIN 
en_menu_items as t2 
on 
t1.parent_id = t2.id 
LEFT JOIN 
en_menu_items as t3 
on 
t2.parent_id = t3.id 
) as depth_table 
ORDER BY 
level 

是吧..