寻找顶级父母(递归)

时间:2017-09-12 07:51:43

标签: php mysql

产品表:

id | id_parent | margin
------------------------
1  | NULL      | 10
2  | 1         | 20
3  | NULL      | 15
4  | 2         | 10
5  | 4         | 25

从上面的数据中,如何获得产品树的保证金总额(id:5)?它没有固定的深度,它是动态的。

我目前通过PHP迭代(递归mysqli_query)来实现这一点,但它消耗了巨大的主机内存(错误508)。

这是PHP函数:

function get_margintotal($product) {
    global $link;

    $query = "SELECT id_parent, margin FROM `products` WHERE id = ".$product['id_parent'];
    if (!$temp_products = mysqli_query($link, $query)) {
        die(json_encode(array("errmsg" => "Selecting supplier's margin.")));
    }
    $temp_product = mysqli_fetch_assoc($temp_products);
    $temp_product['margin'] = $product['margin'] + $temp_product['margin'];

    if (isset($temp_product['id_parent'])) {
        return get_margintotal($temp_product);
    }
    else {
        return $temp_product['margin'];
    }
}

所以我想知道是否可以在MySQL中完成动态迭代,或者如何优化函数以减少服务器内存使用量?

谢谢。

2 个答案:

答案 0 :(得分:1)

使用带变量的递归的MySQL解决方案。

CREATE TABLE `finding_top_parent_recursive_46170847` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `id_parent` int(11) DEFAULT NULL,
  `margin` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;


INSERT INTO `finding_top_parent_recursive_46170847` (`id`, `id_parent`, `margin`)
VALUES
    (1, NULL, 10),
    (2, 1, 20),
    (3, NULL, 15),
    (4, 2, 10),
    (5, 4, 25);


-- set the seed leaf id
set @id = 5 ;
select sum(margin) margin from (
    -- include the seed 
    select id, margin from finding_top_parent_recursive_46170847 products
    where id = @id
    union all
    -- get the parents
    select @id := ( 
        select id_parent 
        from finding_top_parent_recursive_46170847 products
        where id = @id ) id,
        ( select margin 
        from finding_top_parent_recursive_46170847 products
        where id = @id ) margin
    from 
    finding_top_parent_recursive_46170847 products
    where @id is not null
) margins

-- results
margin
65

来自

的递归mysql结果的想法

https://www.google.com.au/search?q=mysql+recursive+left+join

https://dba.stackexchange.com/questions/46127/recursive-self-joins

Hierarchical queries in MySQL

答案 1 :(得分:0)

如果你知道最大深度,比方说5,你可以在一个查询中用4 LEFT JOINS计算总和:

SELECT p1.margin + IFNULL(p2.margin, 0) + IFNULL(p3.margin, 0) + IFNULL(p4.margin, 0) + IFNULL(p5.margin, 0)
FROM product AS p1
    LEFT JOIN product AS p2 ON p1.id_parent = p2.id
    LEFT JOIN product AS p3 ON p2.id_parent = p3.id
    LEFT JOIN product AS p4 ON p3.id_parent = p4.id
    LEFT JOIN product AS p5 ON p4.id_parent = p5.id
WHERE p1.id = :givenId