从数据库中获取分层格式的类别

时间:2013-03-22 12:58:39

标签: php mysql

我有MySQL类别表如下。其中parent字段指示父类别的IDhassub字段指示类别是否具有子类别。 (我使用PHP作为基础。)

************************************
| ID  | parent  | name   | hassub  |
************************************
| 1   | 0       | Nature | 1       |
| 2   | 1       | foo    | 0       |
| 3   | 1       | bar    | 1       |
| 4   | 3       | bar1   | 0       |
| 5   | 0       | Anime  | 0       |
************************************

现在以分层格式获取所有类别,有没有办法在尽可能少的MySQL查询中执行此操作?

  
  • 主要分类1
    • 子类别1
    • 子类别   2
    • 子类别3
  • 主要类别2
  •   
  • 主要类别3
    • 子类别1
    • 子类别   2

我现在正在做的是获取parent = 0的所有行,然后查询每一行以获取它的子类别。

3 个答案:

答案 0 :(得分:3)

这是在文本编辑器中手写的...我没有一个开发环境,所以如果这只是错误或包含错别字,那么appologies。

但不管我认为这个想法是否清晰/健全。

$sql将是:

SELECT 
    parent.id as parentid,
    parent.[name] as parentname,
    child.[name] as childname

FROM
    category child

    left join category parent -- Can't exclude parents with no children, else they won't appear in the list!
    on child.parent = parent.id

ORDER BY
    parentid

然后PHP将是:

function categoryLevels(){
    $bullet = "*"; // You can specify your HTML/CSS :-)
    $indent = "   "; // You can specify your HTML/CSS :-)

    $sql = "_as above_";
    $query = mysql_query($sql);
    $lastParentId = 0;
    while($row = mysql_fetch_array($query)){
        $parentId = $row['parentid']
        if ($parentId != 0) {
            if ($parentId != $lastParentId) {
                echo $bullet . $row['parentname']
                $lastParentId = $parentId;
            }
            if (!is_null($row['childname']) { // this line is psuedo-code! - don't know the php equiv for is_null, sorry.
                echo $indent . $bullet . $row['childname'];
            }
        }
    }
}

这个要点基本上是:

  1. 获取所有类别的结果集(不包括没有父母的类别),按其所属的父级排序
  2. 迭代该结果集,并且对于父级中的每个更改,输出带有父名称的“标题”。
  3. 输出孩子。
  4. 编辑它不那么复杂(也更快)。现在,SQL只是完全排除父行,而不是用PHP中的IF语句排除它们。

答案 1 :(得分:0)

您可以使用递归方法

function getSubCategories($parent_id = 0){

    $sql = "select col1, col2,... from table_name where parentt_id = ".$parent_id;
    $query = mysql_query($sql);
    while($row = mysql_fetch_array($query)){
        echo $row['category_name'];
        getSubCategories($row['category_id']);
    }
}

getSubCategories();

这将以分层格式打印所有类别。您可以使用这种方式生成分层类别格式。

答案 2 :(得分:0)

您可以加入数据(提供您知道的深度)。

例如:

CREATE TABLE`test` (
  `id` INT(11) unsigned NOT NULL AUTO_INCREMENT,
  `parent` INT(10) unsigned NOT NULL DEFAULT '0',
  `name` VARCHAR(50),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO test (id, parent, name) values
(1, 0, 'Nature'),
(2, 1, 'Foo'),
(3, 1, 'Bar'),
(4, 3, 'Bar1'),
(5, 0, 'Anime');

我们知道有两个级别,因此只需要一个连接 - 每个级别都需要连接,这是adjacancy list模型的许多缺点之一。

SELECT a.name AS 'Level 1', b.name AS 'Level 2' FROM test AS a
LEFT JOIN test AS b
  ON b.parent = a.id
WHERE a.parent = 0

这会给出输出:

+---------+---------+
| LEVEL 1 | LEVEL 2 |
---------------------
|  Nature |     Foo |
|  Nature |     Bar |
|   Anime |  (null) |
+---------+---------+

从此输出中,您可以遍历数组并填充项目符号列表。

相关问题