获取所有类别及其子项

Arn*_*lis 19 php mysql recursion

为了回答这个问题,我将给予100点奖励积分

所以我对递归有一个非常困难的问题 - 如何获得所有项目的类别和包含该父项的所有子项,并且直到最后更深入?

我有桌子:

+----+---------------+-----------------+
| id | category name | category_parent |
+----+---------------+-----------------+
| 1  | cars          |        0        |
+----+---------------+-----------------+
| 2  | real estate   |        0        |
+----+---------------+-----------------+
| 3  | clothes       |        0        |
+----+---------------+-----------------+
| 4  | bmw           |        1        |
+----+---------------+-----------------+
| 5  | audi          |        1        |
+----+---------------+-----------------+
| 6  | 100           |        5        |
+----+---------------+-----------------+
| 7  | 80            |        5        |
+----+---------------+-----------------+
| 8  | A4            |        5        |
+----+---------------+-----------------+
| 9  | QUATRO        |        8        |
+----+---------------+-----------------+
| 10 | TDI           |        8        |
+----+---------------+-----------------+
| 11 | Black         |        9        |
+----+---------------+-----------------+
| 12 | White         |        9        |
+----+---------------+-----------------+
| 13 | 2 doors       |        11       |
+----+---------------+-----------------+
| 14 | 5 doors       |        11       |
+----+---------------+-----------------+
Run Code Online (Sandbox Code Playgroud)

我的产品表看起来像这样:

+----+---------------+-----------------+
| id | category_id   | name            |
+----+---------------+-----------------+
Run Code Online (Sandbox Code Playgroud)

例如,我想计算所有cars类别的项目.所以基本上我应该传递这个类别的ID,(1)并以某种方式进行递归来计算所有项目.但是我不知道如何处理它,因为那个类别的孩子可能是无限的.

所以,当我想知道那个父母计数的所有项目时,我应该做这样的事情:

1++:
  4++
  5++:
    6++
    7++
    8++:
      9++:
        11++:
           13++
           14++
        12++
      10++
Run Code Online (Sandbox Code Playgroud)

我希望你能理解我需要什么,并给我任何可以帮助我的建议.

而且,这是我到目前为止所做的开始 - 我可以实现它,但将来我会陷入递归...所以它没有价值.

public function get_category_tree_id_list($cat_id, $list_array = FALSE)
{
    if ( !$list_array ){
        $items = $this->system->_getCustomTableData('categories', array(array('category_parent' => $cat_id)), 'id DESC');
        $this->__tmp['id_list'] = [];
        foreach ( $items as $key => $value ) {
            $this->__tmp['id_list'][] = $value['id'];
        }
    }        
}
Run Code Online (Sandbox Code Playgroud)

dav*_*ave 14

您很可能想要嵌套集.它们设置起来有点棘手,但使查询更简单.所以,与其类别的父母,你将有两列- lftrgt.左侧和右侧基本上是类别的边界,如果项目的类别ID在这些值之间,您知道它是该类别的子级.

+----+---------------+-----+------+
| id | category name | lft | rgt  |
+----+---------------+-----+------+
| 1  | cars          |  1  |  24  |
+----+---------------+-----+------+
| 2  | bmw           |  2  |  3   |
+----+---------------+-----+------+
| 5  | audi          |  4  | 23   |
+----+---------------+-----+------+
| 6  | 100           |  5  |  6   |
+----+---------------+-----+------+
| 7  | 80            |  7  |  8   |
+----+---------------+-----+------+
| 8  | A4            |  9  | 22   |
+----+---------------+-----+------+
| 9  | TDI           |  10 | 11   |
+----+---------------+-----+------+
| 10 | Quatro        |  12 | 21   |
+----+---------------+-----+------+
| 11 | Black         |  13 | 18   |
+----+---------------+-----+------+
| 12 | White         |  19 |  20  |
+----+---------------+-----+------+
| 13 | 2 doors       |  14 |  15  |
+----+---------------+-----+------+
| 14 | 5 doors       |  16 | 17   |
+----+---------------+-----+------+
Run Code Online (Sandbox Code Playgroud)

然后,要获得汽车类别中的项目数量,您可以像这样超级简单地完成:

SELECT categories.name, items.id, items.category_id, items.name 
FROM categories 
LEFT JOIN items 
    ON (items.category_id BETWEEN categories.lft AND categories.rgt)
WHERE categories.category_name = 'cars'
Run Code Online (Sandbox Code Playgroud)

显然,您只需更改category_name任何类别中的项目并获取项目.

抱歉,由于某种原因,我在此处上传图片时图像已旋转,但如果您将类别绘制为圆圈,然后对线条进行编号,则可以看到左右值的值.

我只做了汽车,因为我认为你可以推断出其他类别.

在此输入图像描述

所以,如果你写出这样的类别:

Cars(BMW(), Audi(100(),80(),A4(TDI(),Quatro(Black(2dr(),5dr()), White())))
Run Code Online (Sandbox Code Playgroud)

然后你可以用数字标记你的括号:

Cars[1]->(BMW[2]->()<-[3], Audi[4]->(100[5]->()<-[6],80[7]->()<-[8],A4[9]->(TDI[10]->()<-[11],Quatro[12]->(Black[13]->(2dr[14]->()<-[15], 5dr[16]->()<-[17])<-[18], White[19]->()<-[20])<-[21])<-[22])<-[23])<-[24]
Run Code Online (Sandbox Code Playgroud)

或者,如果您将其绘制为树状,则可以将其标记为这样,在此处用最大的数字标记最左边的节点,并在标记所有子节点时仅标记正确的节点:

在此输入图像描述


waj*_*jih 5

我有一个新想法,我认为这会很好。想法是这样的:在category_parent列中,我们将插入对此节点的所有父节点的引用。

+----+----------------+----------------+
| 编号 | 类别名称 | 等级制度 |
+----+----------------+----------------+
| 1 | 汽车 | 1 |
+----+----------------+----------------+
| 2 | 房地产| 2 |
+----+----------------+----------------+
| 3 | 衣服| 3 |
+----+----------------+----------------+
| 4 | 宝马| 1-4 | 1-4
+----+----------------+----------------+
| 5 | 奥迪 | 1-5 | 1-5
+----+----------------+----------------+
| 6 | 100 | 100 1-4-6 | 1-4-6
+----+----------------+----------------+
| 7 | 80| 1-4-7 | 1-4-7
+----+----------------+----------------+
| 8 | A4| 1-4-8 | 1-4-8
+----+----------------+----------------+
| 9 | 四轮| 1-4-8-9 | 1-4-8-9 |
+----+----------------+----------------+
| 10 | 10 TDI | 1-4-8-10 | 1-4-8-10 |
+----+----------------+----------------+
| 11 | 11 黑色| 1-4-8-9-11 | 1-4-8-9-11 |
+----+----------------+----------------+
| 12 | 12 白色| 1-4-8-9-12 | 1-4-8-9-12 |
+----+----------------+----------------+
| 13 | 2 门 | 1-4-8-9-11-13 | 1-4-8-9-11-13 |
+----+----------------+----------------+
| 14 | 14 5 门 | 1-4-8-9-11-14 | 1-4-8-9-11-14 |
+----+----------------+----------------+

如果您查看我更新的表格,您会发现每条记录都有与其父项的链接,不仅是直接记录,而且还包括所有父项。对于这项工作,我做了一些修改以插入为:

Insert into table_name (category_name, hierarchy) values ('new_name', (concat(parent_hierarch, '-', (SELECT Auto_increment FROM information_schema.tables WHERE table_name='table_name'))))
Run Code Online (Sandbox Code Playgroud)

现在让我们进行您想要的查询:

1- 汽车的所有子类别:

select * from table_name where hierarchy like '1-%'
Run Code Online (Sandbox Code Playgroud)

2-如果您需要黑色的所有父级,您只需输入:

select * from table_name where hierarchy = '1-4-8-9' or hierarchy = '1-4-8' or hierarchy = '1-4' or hierarchy = '1'
Run Code Online (Sandbox Code Playgroud)

(您可以从 php 构建该查询,在“-”字符处分割层次结构字段)

3- 查看所有类别,包括级别和直接父级:

select *, SUBSTR(hierarchy, 1, (LENGTH(hierarchy) - LENGTH(id) - 1)) as parent, LENGTH(hierarchy) - LENGTH(REPLACE(hierarchy, '-', '')) as level From table_name
Run Code Online (Sandbox Code Playgroud)
+----+----------------+-----------------+------------------------ -+--------+
| 编号 | 类别名称 | 等级制度 | 家长 | 水平|
+----+----------------+-----------------+------------------------ -+--------+
| 1 | 汽车 | 1 | | 0 |
+----+----------------+-----------------+------------------------ -+--------+
| 2 | 房地产| 2 | | 0 |
+----+----------------+-----------------+------------------------ -+--------+
| 3 | 衣服| 3 | | 0 |
+----+----------------+-----------------+------------------------ -+--------+
| 4 | 宝马| 1-4 | 1-4 1 | 1 |
+----+----------------+-----------------+------------------------ -+--------+
| 5 | 奥迪 | 1-5 | 1-5 1 | 1 |
+----+----------------+-----------------+------------------------ -+--------+
| 6 | 100 | 100 1-4-6 | 1-4-6 1-4 | 1-4 2 |
+----+----------------+-----------------+------------------------ -+--------+
| 7 | 80| 1-4-7 | 1-4-7 1-4 | 1-4 2 |
+----+----------------+-----------------+------------------------ -+--------+
| 8 | A4| 1-4-8 | 1-4-8 1-4 | 1-4 2 |
+----+----------------+-----------------+------------------------ -+--------+
| 9 | 四轮| 1-4-8-9 | 1-4-8-9 | 1-4-8 | 1-4-8 3 |
+----+----------------+-----------------+------------------------ -+--------+
| 10 | 10 TDI | 1-4-8-10 | 1-4-8-10 | 1-4-8 | 1-4-8 3 |
+----+----------------+-----------------+------------------------ -+--------+
| 11 | 11 黑色| 1-4-8-9-11 | 1-4-8-9-11 | 1-4-8-9 | 1-4-8-9 | 4 |
+----+----------------+-----------------+------------------------ -+--------+
| 12 | 12 白色| 1-4-8-9-12 | 1-4-8-9-12 | 1-4-8-9 | 1-4-8-9 | 4 |
+----+----------------+-----------------+------------------------ -+--------+
| 13 | 2 门 | 1-4-8-9-11-13 |1-4-8-9-11 | 5 |
+----+----------------+-----------------+------------------------ -+--------+
| 14 | 14 5 门 | 1-4-8-9-11-14 |1-4-8-9-11 | 5 |
+----+----------------+-----------------+------------------------ -+--------+

这是一个新想法,需要一些改进。我希望你能从中受益。