MySQL单个父子表中分层数据的乘法

标签 mysql hierarchical-data

我正在开发一个项目,其 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_percentagehierarchy_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/

相关文章:

MySql 从不同的随机类别中获取随机元素

mysql - 这个MySQL触发器是线程安全的吗?

mysql - 授予用户权限以仅查看 MySQL View 而不是其他 View

php - MySQL 单例类与递归函数冲突(PHP)

php - 具有选定和禁用模式的类别层次结构 (PHP-MySQL)

mysql - 如何创建MySQL分层递归查询

mysql - 使用 powershell 合并两个相似且两列不同的表

mysql - 使用单个查询在 mysql 表中查找多个 child 的所有 parent

java - 使用 Java 聚合两个层次树的笛卡尔积

php - 有两个表的邻接表模型