1

我有如下的 MySQL 类别表。哪个parent字段告诉ID父类别,hassub字段告诉类别是否有子类别。(我使用 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然后查询每一行以获取它的子类别。

4

3 回答 3

3

这是在文本编辑器中手写的......我没有方便的开发环境,所以如果这只是完全错误或包含拼写错误,请原谅。

但无论如何,我认为这个想法是清晰/合理的。

$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. 输出孩子。

将其编辑为不那么复杂(并且更快)。现在 SQL 完全排除了父行,而不是用IFPHP 中的语句排除它们。

于 2013-03-22T13:59:13.237 回答
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();

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

于 2013-03-22T13:26:57.780 回答
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');

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

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

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

于 2013-03-22T13:51:23.670 回答