sql - 递归查询计算父值

标签 sql sql-server t-sql

我有 2 个表“人员”和“销售”。在 Person 中, child 和 parent 之间存在关系,我想使用以下条件计算 20% 的 parent 值

人数

Id | ParentId | Name
1    NULL       Tom
2    1          Jake
3    2          Kate
4    3          Neil

销售

PersonId | Sale
4          500

我想要得到这样的结果

Id | ParentId | Name | Sale
1    Null       Tom    100  <-- (500*20)/100 left 400
2    1          Jake   80   <-- (400*20)/100 left 320
3    2          Kate   64   <-- (320*20)/100 left 256
4    3          Neil   256  <-- (320*80)/100 

我编写了这个查询,但它没有给出适当的结果

;WITH cte_persons
AS
(
    SELECT p.Id, p.ParentId, p.Name, s.Price FROM Persons AS p
        INNER JOIN Sales AS s ON s.PersonId = p.Id
    UNION ALL
    SELECT p.Id, p.ParentId, p.Name, CAST((c.Price - (c.Price*80)/100) AS DECIMAL(6, 2)) FROM @Persons AS p
        INNER JOIN cte_persons AS c ON c.ParentId = p.Id
)
SELECT * FROM cte_persons

最佳答案

这应该是一个两步算法。首先遍历层次结构以获得最高级别。然后以相反的顺序应用该级别。

WITH cte_persons
AS
(
    SELECT 1 as level, p.Id, p.ParentId, p.Name, s.Price, p.Id AS base
    FROM Persons AS p
    INNER JOIN Sales AS s ON s.PersonId = p.Id
    UNION ALL
    SELECT level + 1, p.Id, p.ParentId, p.Name, c.Price, c.base
    FROM Persons AS p
    INNER JOIN cte_persons AS c ON c.ParentId = p.Id
)
SELECT Id, ParentId, Name,
   CASE level WHEN 1 
   THEN price - sum(delta) over(partition by base order by level desc) + delta 
   ELSE delta END sale
FROM ( 
   SELECT *,
     (power (0.8000, max(level) over(partition by base) - level) * 0.2) * price delta
   FROM cte_persons
) t
ORDER BY id;

db<>fiddle

关于sql - 递归查询计算父值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69371407/

相关文章:

SQL 'Round' 将日期更新为一周中的给定日期

sql - 是否可以循环遍历整个流程 n 次?

sql-server - 在 SQL Server 中实现审计跟踪的最佳方法?

Sql:选择所有类型的条件都为 true 的位置

sql - 查询以查看针对相同 ProductId 的 ProductName 计数

sql - sql查询soap获取以s命名的第一个元素:Body

sql - 如何找出哪些 SQL 查询被阻止以及哪些内容阻止了它们?

sql - * 和显式字段列表的结果不同?

sql-server - 如何在 SQL-Server 中创建一个只能访问一张表并且只能插入行的用户

sql-server - 重命名AD中的安全组,并映射SQL登录