Ebeveyn sonra çocuk yerlere tarafindan MySQL sorgusu

6 Cevap php

Benim veritabanındaki sayfaları bir tablo var, her sayfa aşağıdaki gibi bir ebeveyne sahip olabilir:

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

Ne daha fazla bir seviye varsa, üç düzeyde maksimum olacak yine ebeveyn o çocuk o çocuk tarafından sipariş edilen tüm sayfaları seçmek için en iyi MySQL sorgusu olacaktır. Yukarıdaki örnekte, istenen sırayı üretecektir:

Home
Sitemap
Products
    Product 1
        Product 1 Review Page
    Product 2

6 Cevap

Ben bunu düzeyinde ve mağaza denilen, sizin tablodaki düğüm düzeyini bir daha fazla alan koymak ve daha sonra ebeveyn tarafından daha sonra düzeyine göre sorgu sıralamak gerektiğini düşünüyorum.

Eğer modeli ile sopa varsa, ben bu sorguyu öneririz:

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;

Sonuca örnek ayarlayın:

+-----+-------------------------+-------------------+
| 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)

İZAH Çıktı:

+------+--------------------+--------------+--------+---------------+---------+---------+--------------------------+------+----------------+
| 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)

Ben bu tablo düzeni kullanılır:

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`)
);

Ben performansını artırmak için parent_id bir dizin dahil olduğunu unutmayın.

Eğer tablo şema üzerinde bazı denetim varsa, bunun yerine iç içe bir dizi temsil kullanarak düşünebilirsiniz. Mike Hillyer bu konuda bir makale yazdı:

Managing Hierarchical Data in MySQL

akıllı değil daha çok çalışmak:

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

o kadar ..

Ugh. Ağaçları içeren bu gibi sorguları bunu düzeyleri herhangi bir sayı için ölçeklenebilir olmasını istiyorsanız, size her seviyede ağaç birkaç bina kadar kullanacağız, tek bir sorgu ile bunu yapmayacağım, genellikle can sıkıcı ve vardır.

Eh, her zaman tek bir sorguda tüm almak ve PHP işleyebilir. Muhtemelen bir ağaç almak için simplier yol olacaktır.