【问题标题】:Counting values from a child level category in a tree, and applying to all parents in PHP or MYSQL计算树中子级类别的值,并在 PHP 或 MYSQL 中应用于所有父级
【发布时间】:2015-07-10 11:34:59
【问题描述】:

我在 mysql 中有最多 5 级的电子商务网站类别树,树是根据 parent_id 方法生成的,我在表 total 中还有一个列来显示每个类别中有多少产品。

一周前我被要求实现一个新功能,显示每个类别的 parent_id 中有多少产品,如下面的 PHP 数组中的数据库表值示例所示。

原始数组如下:

$array = [
'101' => [
    'total' => null,
    'array' => [
        '102' => 4,
        '103' => 24,
        '104' => [
            'total' => null,
            'array' => [
                '105' => 9,
                '106' => [
                    'total' => null,
                    'array' => [
                        '107' => 2,
                        '108' => 3
                    ]
                ],
                '109' => [
                    'total' => null,
                    'array' => [
                        '110' => 2,
                        '111' => 3
                    ]
                ]
            ],
        ],
        '112' => [
            'total' => null,
            'array' => [
                '113' => 2,
                '114' => 3
            ]
        ]
    ]
],
'115' => [
    'total' => null,
    'array' => [
        '116' => 2,
        '117' => 3
    ]
]];

这周我尝试了很多方法,但对我来说没有任何效果,使用递归递归,但这也无济于事,我仍然不确定如何从每个最高树级别向后递归。

您会采用什么方法来计算和更新数据库中的这些值?

以下是mysql表结构和虚拟数据:

INSERT INTO dummy_categories (id,parent_id,total) VALUES (101,0,NULL),(102,101,4),(103,101,24),(104,101,NULL), (105,104,9),(106,104,NULL),(107,106,2),(108,106,3), (109,104,NULL),(110,109,2),(111,109,3),(112,101,NULL), (113,112,2),(114,112,3),(115,0,NULL),(116,115,2),(117,115,3);

【问题讨论】:

  • 您的阵列有多大?为什么不从下往上重新计算所有总数?您可能会发现整个过程只需要一瞬间,尝试只更新树的一部分是没有意义的。
  • 我讨厌 PHP 数组中的嵌套导航——你总是想向后工作;例如该 URL 将为您提供类别 ID 108,然后您需要确定哪些分支在它之上是活动的 - 这可能会导致可怕的递归函数或循环。我发现处理这个问题的最佳方法是从中创建一个 XML (DOMDocument) 对象,并在您的 DOM ID 中使用您的数据库 ID。然后,您可以getElementById 遍历节点树 up ...在这种情况下,您可能还可以通过计算节点子节点来计算您的总数。

标签: php mysql


【解决方案1】:

这是我向所有父母总结孩子总数的方式:

class CountChildValuesToParents {
    private $_nodes;
    private $_node;
    private $_parentId;
    private $_data;

    public function updateData($data) {
        $this->_data = [];
        $this->_node = 0;
        $this->_nodes = [];
        $data = $this->buildTree($data);
        $this->update($data, $data[0]);
        $this->emptyNodes();
        foreach ($this->_data as $id => $total) {
            UPDATE dummy_categories SET total=$total WHERE id=$id
        }

    }
    private function buildTree($data) {
        $cats = [];
        foreach ($data as $v) {
            $cats[$v['parent_id']][$v['id']] = $v;
        }
        return $cats;
    }
    private function update(&$p, $childs) {
        foreach ($childs as $id => $v) {
            if (isset($p[$id])) {
                if (!$v['parent_id']) {
                    $this->emptyNodes();
                } elseif ($v['parent_id'] != $this->_parentId) {
                    $this->emptyNode($v['parent_id']);
                }
                $this->_parentId = $id;
                $this->_nodes = [$id => 0] + $this->_nodes;
                $this->update($p, $p[$id]);
            } elseif (isset($v['total'])) {
                $this->updateNodes((int)$v['total']);
            }
        }
    }
    private function updateNodes($value) {
        foreach ($this->_nodes as $id => $v) {
            $this->_nodes[$id] += $value;
        }
    }
    private function emptyNode($parentId) {
        if (!isset($this->_nodes[$parentId])) {
            die('ERROR: Node in _nodes not exist.');
        }

        for ($i = 0; $i < count($this->_nodes); $i++) {
            $key = key($this->_nodes);
            if ($key == $parentId) {
                return;
            }

            if (isset($this->_data[$key])) {
                die('ERROR: Node in _data already exists.');
            }
            $this->_data[$key] = $this->_nodes[$key];
            unset($this->_nodes[$key]);
        }
    }
    private function emptyAllNodes() {
        foreach ($this->_nodes as $k => $v) {
            if (isset($this->_data[$k])) {
                die('ERROR: Node in _data already exists.');
            }
            $this->_data[$k] = $v;
        }
        $this->_nodes = [];
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-06
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多