在MySQL中数树结构中的分支数

huangapple go评论132阅读模式
英文:

Number branches in a tree structure with MySQL

问题

我明白你的需求是将树状结构转换为矩阵结构,并且你想知道如何在递归函数中计算Branch。你可以使用以下方法在递归查询中计算Branch:

WITH RECURSIVE tree AS
(
    SELECT CAST(Node AS CHAR(255)) AS Path, 1 AS Branch, 1 AS Level, Node, Data
    FROM treestructure t WHERE Node = 10
    UNION ALL
    SELECT CONCAT(Path, '.', t2.Node) AS Path,
           CASE WHEN LENGTH(Path) < LENGTH(tree.Path) THEN Branch + 1 ELSE Branch END,
           Level + 1,
           t2.Node,
           t2.Data
    FROM treestructure t2
    INNER JOIN tree ON t2.Parent = tree.Node
)
SELECT * FROM tree
ORDER BY Path;

上述代码中,我在递归查询中使用了CASE语句来计算Branch。如果新的路径(Path)较短,说明它是一个新的分支,所以我们将Branch加1。这应该能够帮助你在结果中正确计算Branch。

希望这能帮助你完成树结构到矩阵结构的转换。如果你有其他问题,请随时提出。

英文:

My task is to transform a tree structure to a matrix structure in order to present it in a report.
I'm using Delphi 11.3, TADOQuery and MySQL version 8.

The tree structure that I whant to transform to a matrix look like this showing the node Id and it's data.

在MySQL中数树结构中的分支数

coming from table treestructure where Nodes and Parents are identified with an Id,

Table treestructure

Idx Node Parent Data
1 10 NULL AA
2 20 10 BB
3 30 20 CC
4 40 30 DD
5 50 20 EE
6 60 50 FF
7 70 20 GG

Where the Row in my coming matrix is the number of the branch in the tree as showed by numbers within () below:

在MySQL中数树结构中的分支数

To get the data to the matrix I use a RECURSIVE call like:

WITH RECURSIVE tree AS
(
 SELECT CAST(Node AS CHAR(255)) AS Path, 1 AS Branch, 1 AS Level, Node, Data
        FROM treestructure t WHERE Id = 10
 UNION ALL
 SELECT CONCAT(Path,&quot;.&quot;,t2.Node) AS Path,
        Branch // How to count up the Branch????, 
        Level + 1,
        t2.Node, 
        t2.Data 
   FROM treestructure t2 
 INNER JOIN tree ON t2.Parent = tree.Node
)
SELECT * FROM tree
ORDER BY Path

which give me following result that I can transform to my matrix by using Branch and Level in combination.

Path Branch Level Node Parent Data
10 1 1 10 NULL AA
10,20 1 2 20 10 BB
10,20,30 1 3 30 20 CC
10,20,30,40 1 4 40 30 DD
10,20,50 2 3 50 20 EE
10,20,50,60 2 4 60 50 FF
10,20,70 3 2 70 20 GG

But my problem is that I can't find out how to calculatet or count up Branch within the recursive function.
One factor to use could be when path is shorter than the previous path then count upp branch with one. But how to do that in a query?

The final result will look like below after transforming the result above.

Branch c1 c2 c3 c4
1 AA BB CC DD
2 EE FF
3 GG

答案1

得分: 1

...我的问题是我不知道如何计算或计数分支...

WITH RECURSIVE tree AS
(
 SELECT CAST(Node AS CHAR(255)) AS Path, 1 AS Branch, 1 AS Level, Node, Data
        FROM treestructure t WHERE Node = 10
 UNION ALL
 SELECT CONCAT(Path, ",", t2.Node) AS Path,
        0 Branch , 
        Level + 1,
        t2.Node, 
        t2.Data 
   FROM treestructure t2 
 INNER JOIN tree ON t2.Parent = tree.Node
)
select replace(path, ',', '.') path, level, node, data, 
       sum(ifnull(mrk, 1)) over (order by path) branch
from (
  select path, level, node, data, 
         1-sign(find_in_set(lag(node) over (order by path), path)) mrk
  FROM tree ) t
ORDER BY Path

dbfiddle演示

  • 在递归查询中使用逗号而不是点(或者在递归中创建另一列,用逗号分隔),
  • 我们需要这个逗号来使用find_in_set。每当前一节点(lag)在当前行路径中不存在时,这意味着它是新分支,此行标记为1 mrk
  • 使用分析求和来计算标记行数。这个总和就是您的branch值。
  • 现在您已经有了一切来基于levelbranch的值创建数据透视表,
  • 如果需要,替换路径中的逗号为点。
英文:

...my problem is that I can't find out how to calculate or count up Branch...

WITH RECURSIVE tree AS
(
 SELECT CAST(Node AS CHAR(255)) AS Path, 1 AS Branch, 1 AS Level, Node, Data
        FROM treestructure t WHERE Node = 10
 UNION ALL
 SELECT CONCAT(Path,&quot;,&quot;,t2.Node) AS Path,
        0 Branch , 
        Level + 1,
        t2.Node, 
        t2.Data 
   FROM treestructure t2 
 INNER JOIN tree ON t2.Parent = tree.Node
)
select replace(path,&#39;,&#39;,&#39;.&#39;) path, level, node, data, 
       sum(ifnull(mrk, 1)) over (order by path) branch
from (
  select path, level, node, data, 
         1-sign(find_in_set(lag(node) over (order by path), path)) mrk
  FROM tree ) t
ORDER BY Path

dbfiddle demo

  • Use comma instead of dot in recursive query (or make another column in recursion, separated with commas),
  • we need this comma to use find_in_set. Whenever previous node (lag) is absent in current row path it means it is new branch, this row is marked as 1 mrk
  • use analytic sum to count marked rows. This sum is your branch value.
  • now you have everything to make pivot based on values level and branch,
  • replace commas in path with dots if needed.

huangapple
  • 本文由 发表于 2023年6月22日 04:33:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526940.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定