(CTE)递归SQL查询

时间:2015-10-26 12:05:38

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

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

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个?

例如;选定的LocationId = 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)

最诚挚的问候,

1 个答案:

答案 0 :(得分:2)

我们可以应用LevelPath来尝试让您的孩子计算,但只显示第一级孩子。我们最终通过路径对资产计数进行分组,该路径是第一级子项的ID。然后只选择最后的第一个级别

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;