【问题标题】:(CTE) Recursive SQL Query(CTE) 递归 SQL 查询
【发布时间】:2016-01-25 12:41:43
【问题描述】:

我对与递归查询相关的一些问题感到困惑。
我正在使用 SQL SERVER 2012
我的场景, 位置是分层定义的, 每个地点都有自己的资产。
我的位置表,例如;

Id  | Name | ParentLocationId
----+------+-----------------  
1   | L1   | NULL  
2   | L2   | 1  
3   | L3   | 1  
4   | L4   | 1  
5   | L5   | 1  
6   | L6   | 4  
7   | L7   | 4  
8   | L8   | 4  
9   | L9   | 2  
10  | L10  | 2  
11  | L11  | 6  
12  | L12  | 6  
13  | L13  | 6  

我的资产表喜欢;

    Id | AssetNo | Description | CurrentLocationId
-------+---------+-------------+------------------
    1  | AN001   |  ADesc      | 1  
    2  | AN002   | BDesc       | 1  

L1 有 1,L2 有 2,L3 有 0,L4 有 3,L5 有 5,L6 有 5,L7 有 1, L8 有 0 个,L9 有 3 个,L10 有 2 个,L11 有 5 个,L12 有 3 个,L13 有 6 个资产

我的问题是,如何获取所选位置的总数 资产数量下降 1 级?

例如;所选位置 ID = 1 (L1) 样本输出是;

    Id | Name | Qty 
-------+------+----- 
    2  | L2   | 7  
    3  | L3   | 0  
    4  | L4   | 23  
    5  | L5   | 5  

另一个例子;选定的 LocationId = 4 (L4)

Id | Name | Qty  
---+------+-----
6  | L6   | 19  
7  | L7   | 1  
8  | L8   | 0  

我试着写了一个查询,

WITH recursiveTable
    AS (SELECT *
         FROM   location l
         WHERE  ParentLocationId = 1
         UNION ALL
         SELECT l.*
         FROM   location l
                INNER JOIN recursiveTable r
                        ON r.Id = l.ParentLocationId),
     allLocations
     AS (SELECT *
         FROM   recursiveTable
         UNION
         SELECT *
         FROM   Location
         WHERE  Id = 0),
     resultset 
     AS (SELECT r.NAME AS LocationName,
                a.*
         FROM   allLocations r
         INNER JOIN Asset a ON a.CurrentLocationId = r.Id
         WHERE  r.DataStatus = 1)

select CurrentLocationId
       ,min(LocationName) as LocationName
       ,count(Id) as NumberOfAsset
from resultset
group by CurrentLocationId

附加的;

Create Table Location
    (
      Id int,
      Name nvarchar(100),
      Description nvarchar(250),
      ParentLocationId int,
      DataStatus int
    )

    Create Table Asset
    (
      Id int,
      AssetNo nvarchar(50),
      Description nvarchar(250),
      CurrentLocationId int,
      DataStatus int
    )

    Insert Into Location Values(1,'L1','LDesc1',NULL,1)
    Insert Into Location Values(2,'L2','LDesc2',1,1)
    Insert Into Location Values(3,'L3','LDesc3',1,1)
    Insert Into Location Values(4,'L4','LDesc4',1,1)
    Insert Into Location Values(5,'L5','LDesc5',1,1)
    Insert Into Location Values(6,'L6','LDesc6',4,1)
    Insert Into Location Values(7,'L7','LDesc7',4,1)
    Insert Into Location Values(8,'L8','LDesc8',4,1)
    Insert Into Location Values(9,'L9','LDesc9',2,1)
    Insert Into Location Values(10,'L10','LDesc10',2,1)
    Insert Into Location Values(11,'L11','LDesc11',6,1)
    Insert Into Location Values(12,'L12','LDesc12',6,1)
    Insert Into Location Values(13,'L13','LDesc13',6,1)

    Insert Into Asset Values (1,'FDB-001','Desc1',1,1)
    Insert Into Asset Values (2,'FDB-002','Desc2',2,1)
    Insert Into Asset Values (3,'FDB-003','Desc3',2,1)
    Insert Into Asset Values (4,'FDB-004','Desc4',4,1)
    Insert Into Asset Values (5,'FDB-005','Desc5',4,1)
    Insert Into Asset Values (6,'FDB-006','Desc6',4,1)
    Insert Into Asset Values (7,'FDB-007','Desc7',5,1)
    Insert Into Asset Values (8,'FDB-008','Desc8',5,1)
    Insert Into Asset Values (9,'FDB-009','Desc9',5,1)
    Insert Into Asset Values (10,'FDB-010','Desc10',5,1)
    Insert Into Asset Values (11,'FDB-011','Desc11',5,1)
    Insert Into Asset Values (12,'FDB-012','Desc12',6,1)
    Insert Into Asset Values (13,'FDB-013','Desc13',6,1)
    Insert Into Asset Values (14,'FDB-014','Desc14',6,1)
    Insert Into Asset Values (15,'FDB-015','Desc15',6,1)
    Insert Into Asset Values (16,'FDB-016','Desc16',6,1)
    Insert Into Asset Values (17,'FDB-017','Desc17',7,1)
    Insert Into Asset Values (18,'FDB-018','Desc18',9,1)
    Insert Into Asset Values (19,'FDB-019','Desc19',9,1)
    Insert Into Asset Values (20,'FDB-020','Desc20',9,1)
    Insert Into Asset Values (21,'FDB-021','Desc21',10,1)
    Insert Into Asset Values (22,'FDB-022','Desc22',10,1)
    Insert Into Asset Values (23,'FDB-023','Desc23',11,1)
    Insert Into Asset Values (24,'FDB-024','Desc24',11,1)
    Insert Into Asset Values (25,'FDB-025','Desc25',11,1)
    Insert Into Asset Values (26,'FDB-026','Desc26',11,1)
    Insert Into Asset Values (27,'FDB-027','Desc27',11,1)
    Insert Into Asset Values (28,'FDB-028','Desc28',12,1)
    Insert Into Asset Values (29,'FDB-029','Desc29',12,1)
    Insert Into Asset Values (30,'FDB-030','Desc30',12,1)
    Insert Into Asset Values (31,'FDB-031','Desc31',13,1)
    Insert Into Asset Values (32,'FDB-032','Desc32',13,1)
    Insert Into Asset Values (33,'FDB-033','Desc33',13,1)
    Insert Into Asset Values (34,'FDB-034','Desc34',13,1)
    Insert Into Asset Values (35,'FDB-035','Desc35',13,1)
    Insert Into Asset Values (36,'FDB-036','Desc36',13,1)

最好的问候,

【问题讨论】:

  • 请阅读How to ask 和How to create a Minimal, Complete, and Verifiable example. 我们需要样本数据和期望输出以更快地找到答案,否则我们将浪费时间猜测您需要什么。您还可以使用 sqlfiddle.com 使用数据创建架构
  • 感谢胡安的建议,我会尝试用数据创建我的架构。
  • 你写的查询结果有什么问题?
  • @TabAlleman 我的目标是计算来自所选位置 1 级的资产数
  • 好的,这与您当前查询的结果有何不同?您的帖子未显示当前查询结果的示例。

标签: sql sql-server recursion common-table-expression hierarchical


【解决方案1】:

我们可以应用Level 和Path 来尝试获取您的孩子计数,但只显示第一级孩子。我们最终按路径对资产计数进行分组,路径是第一级孩子的 ID。然后只选择最后的第一个Level

DECLARE @LocationID INT = 1;

WITH recursiveCTE AS
(
    SELECT 
        *,
        1 AS [Level],
        Id [Path]
    FROM 
        location l
    WHERE 
        l.ParentLocationId = @LocationID
    UNION ALL 
    SELECT 
        l.*,
        [Level] + 1,
        [Path]
    FROM 
        location l
        JOIN recursiveCTE r ON l.ParentLocationId = r.Id
),
countCte AS (
    SELECT 
        [Path] Id,
        COUNT(a.AssetNo) Qty
    FROM recursiveCTE c
    JOIN Asset a ON c.Id = a.CurrentLocationId 
    GROUP BY [Path]
)

SELECT  r.Id,
        r.[Name], 
        COALESCE(c.Qty,0) Qty 
FROM    recursiveCTE r
        LEFT JOIN countCte c ON r.Id = c.Id
WHERE   r.[Level] = 1;

【讨论】:

  • 感谢您的帮助@JamieD77,也感谢您的解决方案。正是我想要的。
  • 我像往常一样想了很多.. 真的不需要在第一个 cte 中获取复杂的路径.. 只需获取 ID.. :)
猜你喜欢
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-28
相关资源
最近更新 更多