递归 CTE 以获得顶级结果

Recursive CTE to get top level results

这是我当前的数据集。

| BIMUnique | Description                                | Quantity | SuperiorUnique | LineCode |
|-----------|--------------------------------------------|----------|----------------|-----------|
| 660084    | Top Level Order Description                | 1        | 0              | 01        |
| 660085    | Second Level Order Description             | 50       | 660084         | 01        |
| 660086    | Second Level Order Description w/sub order | 200      | 660084         | 02        |
| 660087    | Third Level Order Description              | 10       | 660086         | 07        |

我想要这样的东西

| Top Level Description       | Immediate Parent                           | Item Description                           | Navigation (LineCode Concatenation) | Qty |
|-----------------------------|--------------------------------------------|--------------------------------------------|-------------------------------------|-----|
| Top Level Order Description | 0                                          | Top Level Order Description                | 01                                  | 1   |
| Top Level Order Description | Top Level Order Description                | Second Level Order Description             | 01.01                               | 50  |
| Top Level Order Description | Top Level Order Description                | Second Level Order Description w/sub order | 01.02                               | 200 |
| Top Level Order Description | Second Level Order Description w/sub order | Third Level Order Description              | 01.02.07                            | 10  | 

我当前的 CTE 有两个问题 - 首先它不显示顶级父级,只显示直接级。其次 ROW_NUMBER 只计算行数,不反映 LineCode。如果我的最终用户创建了 3 个列表项,然后删除了第 2 个项,系统不会返回并重新排序行号。

WITH bi AS 
    (
        SELECT  
          m.*, 
          CAST(ROW_NUMBER() OVER (ORDER BY m.LineCode) AS VARCHAR(MAX)) COLLATE Latin1_General_BIN AS Tree
        FROM BidItems m with (nolock)
        WHERE m.SuperiorUnique = 0 AND m.JobUnique = '12591'

        UNION ALL

        SELECT  
          m.*,  
          bi.Tree + '.' + CAST(ROW_NUMBER() OVER (PARTITION BY m.SuperiorUnique ORDER BY m.LineCode) AS VARCHAR(MAX)) COLLATE Latin1_General_BIN
        FROM BidItems m with (nolock)
        JOIN bi ON m.SuperiorUnique = bi.BIMUnique
        WHERE m.JobUnique = '12591'
    )

SELECT 
  Job.Number,
  Job.Description,
  bi.Tree,
  bi.LineCode,
  bi.Description,
  bi.Quantity,
  bi.TotalCosts,
  bi.*
FROM Job AS job with (nolock)
INNER JOIN bi ON bi.JobUnique = Job.JOBUnique
INNER JOIN BidItems AS sup with (nolock) ON bi.SuperiorUnique = sup.BIMUnique
LEFT JOIN BidItemDetail AS bid with (nolock) ON bid.BidItemUnique = bi.BIMUnique

ORDER BY Bi.Tree

我们使用的是 MSSQL 2012

更新:LineOrder 应该是 LineCode。

考虑以下查询,它从根到叶遍历树。我真的不认为 row_number() 需要生成路径,这显然是由 LineNumbers.

组成的
with cte (TopLevelDescription, ImmediateParent, ItemDescription, Navigation, Qty, BIMUnique)
as (
    select 
        Description, 
        cast(0 as varchar(60)), 
        Description, 
        cast(LineOrder as varchar(max)), 
        Qty, 
        BIMUnique 
    from BidItems
    where SuperiorUnique = 0
    union all
    select 
        c.TopLevelDescription, 
        c.ItemDescription, 
        b.Description, 
        c.Navigation + '.' + b.LineOrder, 
        b.Qty, 
        b.BIMUnique
    from cte c
    inner join BidItems b on b.SuperiorUnique = c.BIMUnique
)
select * from cte

Demo on SQL Server 2012:

TopLevelDescription         | ImmediateParent                            | ItemDescription                            | Navigation | Qty | BIMUnique
:-------------------------- | :----------------------------------------- | :----------------------------------------- | :--------- | --: | --------:
Top Level Order Description | 0                                          | Top Level Order Description                | 1          |   1 |    660084
Top Level Order Description | Top Level Order Description                | Second Level Order Description             | 1.1        |  50 |    660085
Top Level Order Description | Top Level Order Description                | Second Level Order Description w/sub order | 1.2        | 200 |    660086
Top Level Order Description | Second Level Order Description w/sub order | Third Level Order Description              | 1.2.7      |  10 |    660087