用CTE树计算公式

时间:2015-01-28 06:28:19

标签: sql sql-server-2008 sql-cte

数据

我有以下部分数据

id    parent    multiplier    const
--    ------    ----------    -----
 1      NULL          1.10     1.00
 2         1          1.20     2.00
 3         1          1.30     3.00
 4         1          2.40     4.00
 5         2          2.50     5.00
 6         2          2.60     6.00
 7         2          2.70    17.00
 8         3          2.80    18.00
 9         3          3.90    19.00
10         3          3.10     7.00
11         8          3.20     8.00
12         8          3.30     9.00
13         8          3.40    10.00
14         9          4.50    11.00
15        10          4.60    21.00
15        10          4.70    22.00

可以在树中显示如下

1 
+-- 2
|   +-- 5 
|   +-- 6
|   +-- 7 
|     
+-- 3
|   +-- 8 
|   |   +-- 11
|   |   +-- 12
|   |   +-- 13
|   |
|   +-- 9
|   |   +-- 14
|   |
|   +-- 10
|       +-- 15
|       +-- 16
|
+-- 4

用于创建表结构和数据的SQL

DECLARE @table TABLE (Id int, Parent int, multiplier decimal(6,3), Const decimal(6,3));

INSERT INTO @table
SELECT  1, NULL,  1.1,   1.00 UNION
SELECT  2,    1,  1.2,   2.00 UNION
SELECT  3,    1,  1.3,   3.00 UNION
SELECT  4,    1,  2.4,   4.00 UNION
SELECT  5,    2,  2.5,   5.00 UNION
SELECT  6,    2,  2.6,   6.00 UNION
SELECT  7,    2,  2.7,  17.00 UNION
SELECT  8,    3,  2.8,  18.00 UNION
SELECT  9,    3,  3.9,  19.00 UNION
SELECT 10,    3,  3.1,   7.00 UNION
SELECT 11,    8,  3.2,   8.00 UNION
SELECT 12,    8,  3.3,   9.00 UNION
SELECT 13,    8,  3.4,  10.00 UNION
SELECT 14,    9,  4.5,  11.00 UNION
SELECT 15,   10,  4.6,  21.00 UNION
SELECT 15,   10,  4.7,  22.00;

问题

我需要为树中任何节点的根计算递归aX+b公式。换句话说,我需要计算子节点的公式,并将结果值移到父级x并继续计算,直到我到达root。

例如,为x=1250.00计算node 14将是

1.10 * (1.30 *( 3.90 * (4.50 * 1250.00 + 11.00) + 19.00) + 3.00)  + 1.00 = 31463.442

目前我正在使用CTE树和C#进行此操作,但我对其速度和优化不满意。

问题

我可以在SQL服务器上进行此计算,只返回值吗?如果可能,我可以使用CTE导航的树深度是多少?

1 个答案:

答案 0 :(得分:1)

  

我可以在SQL服务器上进行此计算,只返回值吗?

是的,从叶节点执行递归,随时进行计算并在主查询中获取最大值。

with C as
(
  select T.Id,
         T.Parent,
         cast(T.multiplier * @x + T.Const as decimal(19, 3)) as x
  from @table as T
  where T.Id = 14
  union all
  select T.Id,
         T.Parent,
         cast(T.multiplier * C.x + T.Const as decimal(19, 3))
  from C 
    inner join @table as T
      on C.Parent = T.Id
)
select max(C.x) as Value
from C
option (maxrecursion 0);
  

如果可能,我可以导航的树深度是多少   CTE?

默认值为100,但您可以使用maxrecursion进行更改。使用option (maxrecursion 0)时没有限制。

  

我对它的速度和优化感到不满意。

要解决这个问题,你必须展示你实际做的事情。如果您在Id上拥有群集主键,则您提供的示例会获得一个好的计划。

它寻求找到锚点并寻找每次迭代。

enter image description here