CTE đệ quy để tìm Tổng cho tất cả trẻ em


16

Đây là một cây lắp ráp mà tôi muốn tìm kiếm bằng cách sử dụng T-SQLTruy vấn đệ quy (có lẽ CTE) với kết quả mong đợi bên dưới. Tôi muốn biết tổng số tiền trên mỗi lắp ráp cho bất kỳ phần nào.

Có nghĩa là nếu tôi tìm kiếm 'Rivet', tôi muốn biết tổng số ở mỗi cấp trong hội đồng, không chỉ là số trẻ em trực tiếp.

Assembly (id:1)
    |
    |-Rivet
    |-Rivet
    |-SubAssembly (id:2)
    |   |
    |   |-Rivet
    |   |-Bolt
    |   |-Bolt
    |   |-SubSubAssembly (id:3)
    |      |
    |      |-Rivet
    |      |-Rivet
    |
    |-SubAssembly (id:4)
       |-Rivet
       |-Bolt

    DESIRED Results
    -------
    ID, Count
    1 , 6
    2 , 3
    3 , 2
    4 , 1

Hiện tại, tôi có thể nhận được cha mẹ trực tiếp, nhưng muốn biết cách mở rộng CTE của mình để cho phép tôi đưa thông tin này lên trên.

With DirectParents AS(
--initialization
Select InstanceID, ParentID
From Instances i 
Where i.Part = 'Rivet'

UNION ALL
--recursive execution
Select i.InstanceID, i.ParentID
From PartInstances i  INNER JOIN DirectParents p
on i.ParentID = p.InstanceID

)

select ParentID, Count(instanceid) as Totals
from DirectParents
group by InstanceID, ParentID

Results
-------
ID, Count
1 , 2
2 , 2
3 , 2
4 , 1

Tạo kịch bản

CREATE TABLE [dbo].[Instances] ( 
  [InstanceID] NVARCHAR (50) NOT NULL, 
  [Part] NVARCHAR (50) NOT NULL, 
  [ParentID] NVARCHAR (50) NOT NULL, );



INSERT INTO Instances 
Values 
  (1, 'Assembly', 0), 
  (50, 'Rivet', 1), 
  (50, 'Rivet', 1), 
  (2, 'SubAssembly', 1), 
  (50, 'Rivet', 2), 
  (51, 'Bolt', 2), 
  (51, 'Bolt', 2), 
  (3, 'SubSubAssembly', 2), 
  (50, 'Rivet', 3), 
  (50, 'Rivet', 3), 
  (4, 'SubAssembly2', 1), 
  (50, 'Rivet', 4), 
  (51, 'Bolt', 4)

Câu trả lời:


14

CTE đệ quy này ( SQL Fiddle ) sẽ hoạt động với mẫu của bạn:

WITH cte(ParentID) AS(
    SELECT ParentID FROM @Instances WHERE [Part] = 'Rivet'
    UNION ALL
    SELECT i.ParentID FROM cte c
    INNER JOIN @Instances i ON c.ParentID = i.InstanceID
    WHERE i.ParentID > 0
)
SELECT ParentID, count(*) 
FROM cte
GROUP BY ParentID
ORDER BY ParentID
;

Đầu ra

ParentID    Count
1           6
2           3
3           2
4           1

Lưu ý: Bạn đã đề cập trong các nhận xét rằng câu hỏi chỉ chứa một bảng mẫu đơn giản hóa và dữ liệu thực có các chỉ mục phù hợp và xử lý trùng lặp và dữ liệu đầy đủ.

Dữ liệu được sử dụng ( SQL Fiddle ):

DECLARE @Instances TABLE( 
    [InstanceID] int NOT NULL
    , [Part] NVARCHAR (50) NOT NULL
    , [ParentID] int NOT NULL
);

INSERT INTO @Instances([InstanceID], [Part], [ParentID])
VALUES 
    (1, 'Assembly', 0)
    , (50, 'Rivet', 1)
    , (50, 'Rivet', 1)
    , (2, 'SubAssembly', 1)
    , (50, 'Rivet', 2)
    , (51, 'Bolt', 2)
    , (51, 'Bolt', 2)
    , (3, 'SubSubAssembly', 2)
    , (50, 'Rivet', 3)
    , (50, 'Rivet', 3)
    , (4, 'SubAssembly2', 1)
    , (50, 'Rivet', 4)
    , (51, 'Bolt', 4)
;

Câu trả lời tuyệt vời cảm ơn bạn! Có một giải pháp dễ dàng để thực hiện điều này một cách đệ quy cho tất cả các Trường hợp [Lắp ráp, Đinh tán, v.v.] không?
greenhoorn

0

Tôi không chắc là tôi hiểu những gì bạn có ý nghĩa bởi "lượng" và nơi bảng (?) PartInstances và cột idđếm đến từ trong mẫu của bạn nhưng tôi tính toán những gì tôi đoán từ dữ liệu mẫu của bạn.

;with ins as (
select [InstanceID], [Part],[ParentID],0 lvl
from instances where ParentID=0
union all
select i.[InstanceID], i.[Part],i.[ParentID], lvl+1
from instances i 
inner join ins on i.parentid=ins.InstanceID
)
select InstanceID,part,COUNT(*) cnt
from ins
group by instanceid,part

Tôi hy vọng điều này sẽ cung cấp cho bạn một số ý tưởng.

Cập nhật

Tôi hiểu rằng đây là một ví dụ thử nghiệm nhưng dữ liệu của bạn phá vỡ mọi thứ bắt đầu từ đó 1NF. Hầu hết có lẽ bảng của bạn nên được chia làm hai và bình thường hóa.


Xem kết quả trong phần đầu tiên của mã .. những điều đó là mong muốn. Khi tìm kiếm 'Đinh tán', tôi đang tìm cách để có được tổng cộng tất cả các đinh tán được cung cấp bất kỳ mảnh nào trên cây. Ý nghĩa của ví dụID 1 sẽ cho tôi kết quả là 6. Có nghĩa là nó chứa 6 tổng số đinh tán trong cấu trúc cây hoàn chỉnh của nó.
markokstate
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.