วนซ้ำ CTE เพื่อหาผลรวมสำหรับเด็กทุกคน


16

นี่คือต้นไม้ประกอบที่ฉันต้องการค้นหาโดยใช้T-SQLแบบสอบถามซ้ำ(สมมุติCTE) ด้วยผลลัพธ์ที่คาดหวังด้านล่าง ฉันต้องการที่จะรู้จำนวนรวมต่อการชุมนุมที่ได้รับส่วนใดส่วนหนึ่ง

หมายความว่าถ้าฉันค้นหา 'หมุดย้ำ' ฉันต้องการทราบจำนวนรวมในแต่ละระดับภายในการชุมนุมไม่ใช่เฉพาะจำนวนลูกโดยตรง

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

ปัจจุบันฉันสามารถรับผู้ปกครองโดยตรง แต่ต้องการทราบวิธีขยาย CTE ของฉันเพื่อให้ฉันสามารถหมุนข้อมูลนี้ขึ้น

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

สคริปต์สร้าง

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)

คำตอบ:


14

CTE แบบเรียกซ้ำ ( SQL Fiddle ) นี้ควรทำงานกับตัวอย่างของคุณ:

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
;

เอาท์พุต

ParentID    Count
1           6
2           3
3           2
4           1

หมายเหตุ: คุณกล่าวถึงในความคิดเห็นว่าคำถามมีเพียงตารางตัวอย่างที่ง่ายและข้อมูลจริงมีดัชนีที่เหมาะสมและจัดการข้อมูลที่ซ้ำกันและข้อมูลอย่างเพียงพอ

ข้อมูลที่ใช้ ( ซอ 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)
;

คำตอบที่ดีขอบคุณ! มีวิธีง่ายๆในการทำสิ่งนี้ซ้ำสำหรับอินสแตนซ์ทั้งหมด [Assembly, Rivet ฯลฯ ] หรือไม่?
greenhoorn

0

ฉันไม่แน่ใจว่าฉันเข้าใจสิ่งที่คุณหมายถึงโดย "จำนวน" และที่ตาราง (?) ส่วนและคอลัมน์idและจำนวนมาจากตัวอย่างของคุณ แต่ฉันคำนวณสิ่งที่ฉันเดาจากข้อมูลตัวอย่างของคุณ

;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

ฉันหวังว่านี่จะให้ความคิดกับคุณ

ปรับปรุง

ผมเข้าใจว่านี้เป็นตัวอย่างการทดสอบ 1NFแต่แบ่งข้อมูลของคุณทุกอย่างเริ่มต้นจาก ส่วนใหญ่อาจตารางของคุณควรแบ่งเป็นสองและปรับมาตรฐาน


ดูผลลัพธ์ในส่วนแรกของรหัส .. ที่ต้องการ เมื่อค้นหา 'Rivet' ฉันกำลังมองหาหมุดทั้งหมดที่ได้รับจากต้นไม้ ความหมาย instanceID 1 ควรให้ผลลัพธ์แก่ฉันจาก 6 ความหมายมันมีหมุดย้ำทั้งหมด 6 อันในโครงสร้างต้นไม้ที่สมบูรณ์
markokstate
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.