产品表:
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中完成动态迭代,或者如何优化函数以减少服务器内存使用量?
谢谢。
答案 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
答案 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