【问题标题】:Recursive join with SUM使用 SUM 进行递归连接
【发布时间】:2020-11-06 17:37:04
【问题描述】:

我有以下格式的数据:

FromStateID ToStateID Seconds
1           2         10
2           3         20
3           4         15
4           5         5

我需要以下输出

FromStateID ToStateID Seconds
1           2         10
2           3         20
3           4         15
4           5         5
1           3         10+20
1           4         10+20+15
1           5         10+20+15+5
2           4         20+15
2           5         20+15+5
3           5         15+5

此输出按时间顺序显示每个组合中 FromStateIdToStateId 所用的总时间。

请帮忙。

【问题讨论】:

  • 最大 stateid 是 5?或者还有更多?我们需要知道最大数量。你真的想要返回一个诸如“10+20+15+5”之类的字符串吗?或者你想要结果,例如50?
  • 我投票结束这个问题,因为输入和输出的陈述不是问题。
  • 最大状态 id 可能超过 5,我需要秒的总和而不是字符串。我添加它是为了更好地解释它
  • 我一直在研究它并尝试使用自加入来解决这个问题,但意识到这不是要走的路。我知道递归查询可以在这里工作,但我从未使用过它。此外,我已经投入了 1.5 天的时间来提出解决方案,并且由于我的任务是红色的,所以我不能再抽出更多时间了。
  • 是否有循环的可能,例如如果从状态4 到状态1 是可能的,那么你需要处理12341 → ...?

标签: sql sql-server tsql common-table-expression


【解决方案1】:

我认为这是一个遵循链接的递归 CTE:

with cte as (
      select FromStateID, ToStateID, Seconds
      from t
      union all
      select cte.FromStateId, t.ToStateId, cte.Seconds + t.Seconds
      from cte join
           t
           on cte.toStateId = t.FromStateId
     )
select *
from cte;

Here 是一个 dbfiddle。

【讨论】:

    【解决方案2】:

    @Gordon LinOff 是更好的解决方案。以下是实现相同目的的另一种选择。

    您可以使用 CROSS JOIN 和 GROUP BY 实现此目的

    DECLARE @table table(FromStateId int, ToStateId int, seconds int)
    
    insert into @table 
    values
    (1           ,2         ,10),
    (2           ,3         ,20),
    (3           ,4         ,15),
    (4           ,5         ,5 );
    
    ;with cte_fromToCombination as
    (select f.fromStateId, t.tostateId
    from
    (select distinct fromStateId from @table) as f
    cross join
    (select distinct toStateId from @table) as t
    )
    select c.FromStateId, c.ToStateId, t.sumseconds as Total_seconds 
    from cte_fromToCombination as c
    CROSS APPLY 
    (SELECT sum(t.seconds)
    from
    @table as t
    WHERE t.ToStateId <= c.ToStateId
    ) as t(sumseconds)
    where c.tostateId > c.fromStateId
    order by FromStateId,ToStateId
    
    
    
    +-------------+-----------+---------------+
    | FromStateId | ToStateId | Total_seconds |
    +-------------+-----------+---------------+
    |           1 |         2 |            10 |
    |           1 |         3 |            30 |
    |           1 |         4 |            45 |
    |           1 |         5 |            50 |
    |           2 |         3 |            30 |
    |           2 |         4 |            45 |
    |           2 |         5 |            50 |
    |           3 |         4 |            45 |
    |           3 |         5 |            50 |
    |           4 |         5 |            50 |
    +-------------+-----------+---------------+
    
    
    

    【讨论】:

    • 谢谢文卡特。但是在 10 个中,您的查询给出了 3 个正确值和 7 个错误值。我不认为这可以使用连接来实现,但您的查询接近输出正确的值。
    • @AmarSale,我在代码中有一个小错误。固定相同。它现在工作正常。感谢您向我指出相同的内容:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 2018-11-02
    • 2015-02-02
    相关资源
    最近更新 更多