我正在开发一个项目,其 MySQL 数据库包含两个表;人数和百分比。
人员表:
+----+------+--------+ | ID | Name | Parent | +----+------+--------+ | 1 | A | 0 | | 2 | B | 1 | | 3 | C | 2 | | 4 | D | 3 | | 5 | E | 1 | | 6 | F | 0 | +----+------+--------+
百分比表:
+----+------------+ | ID | Percentage | +----+------------+ | 1 | 70% | | 2 | 60% | | 3 | 10% | | 4 | 5% | | 5 | 40% | | 6 | 30% | +----+------------+
我要查找的查询结果应该如下:
+----+------------+----------------+--------+ | ID | Percentage | Calculation | Actual | +----+------------+----------------+--------+ | 1 | 70 | 70% | 70.00% | | 2 | 60 | 70%*60% | 42.00% | | 3 | 10 | 70%*60%*10% | 4.20% | | 4 | 5 | 70%*60%*10%*5% | 0.21% | | 5 | 40 | 70%*40% | 28.00% | | 6 | 30 | 30% | 30.00% | +----+------------+----------------+--------+
计算栏仅用于详细说明。我可以使用任何 MySQL 技术来实现这种分层查询吗?即使百分比表可能包含同一个人的多个条目(百分比)?
最佳答案
解决方案是利用以下链接中描述的函数进行分层查询:
您需要计算乘法,而不是创建PATH
。
解决方案脚本
将其直接复制并粘贴到 mysql 控制台中。我在工作台上运气不太好。此外,还可以通过将 hierarchy_sys_connect_by_path_percentage
和 hierarchy_sys_connect_by_path_percentage_result
合并到一个存储过程中来进一步优化。不幸的是,对于巨大的数据集来说,这可能会相当慢。
设置表和数据
drop table people;
drop table percentages;
create table people
(
id int,
name varchar(10),
parent int
);
create table percentages
(
id int,
percentage float
);
insert into people values(1,' A ',0);
insert into people values(2,' B ',1);
insert into people values(3,' C ',2);
insert into people values(4,' D ',3);
insert into people values(5,' E ',1);
insert into people values(6,' F ',0);
insert into percentages values(1,0.70);
insert into percentages values(2,0.60);
insert into percentages values(3,0.10);
insert into percentages values(4,0.5);
insert into percentages values(5,0.40);
insert into percentages values(6,0.30);
DELIMITER $$
DROP FUNCTION IF EXISTS `hierarchy_sys_connect_by_path_percentage`$$
CREATE FUNCTION hierarchy_sys_connect_by_path_percentage(
delimiter TEXT,
node INT)
RETURNS TEXT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE _path TEXT;
DECLARE _id INT;
DECLARE _percentage FLOAT;
DECLARE EXIT HANDLER FOR NOT FOUND RETURN _path;
SET _id = COALESCE(node, @id);
SELECT Percentage
INTO _path
FROM percentages
WHERE id = _id;
LOOP
SELECT parent
INTO _id
FROM people
WHERE id = _id
AND COALESCE(id <> @start_with, TRUE);
SELECT Percentage
INTO _percentage
FROM percentages
WHERE id = _id;
SET _path = CONCAT( _percentage , delimiter, _path);
END LOOP;
END $$
DROP FUNCTION IF EXISTS `hierarchy_sys_connect_by_path_percentage_result`$$
CREATE FUNCTION hierarchy_sys_connect_by_path_percentage_result(
node INT)
RETURNS FLOAT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE _path TEXT;
DECLARE _id INT;
DECLARE _percentage FLOAT;
DECLARE EXIT HANDLER FOR NOT FOUND RETURN _path;
SET _id = COALESCE(node, @id);
SELECT Percentage
INTO _path
FROM percentages
WHERE id = _id;
LOOP
SELECT parent
INTO _id
FROM people
WHERE id = _id
AND COALESCE(id <> @start_with, TRUE);
SELECT Percentage
INTO _percentage
FROM percentages
WHERE id = _id;
SET _path = _percentage * _path;
END LOOP;
END $$
DELIMITER ;
查询
SELECT hi.id AS ID,
p.Percentage,
hierarchy_sys_connect_by_path_percentage('*', hi.id) AS Calculation,
hierarchy_sys_connect_by_path_percentage_result(hi.id) AS Actual
FROM people hi
JOIN percentages p
ON hi.id = p.id;
结果
+------+------------+-----------------+--------------------+
| ID | Percentage | Calculation | Actual |
+------+------------+-----------------+--------------------+
| 1 | 0.7 | 0.7 | 0.699999988079071 |
| 2 | 0.6 | 0.7*0.6 | 0.419999986886978 |
| 3 | 0.1 | 0.7*0.6*0.1 | 0.0419999994337559 |
| 4 | 0.5 | 0.7*0.6*0.1*0.5 | 0.0210000015795231 |
| 5 | 0.4 | 0.7*0.4 | 0.280000001192093 |
| 6 | 0.3 | 0.3 | 0.300000011920929 |
+------+------------+-----------------+--------------------+
格式化数字很简单,所以我把它留给你...... 更重要的是优化以减少对数据库的调用。
关于MySQL单个父子表中分层数据的乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20974937/