Recursive CTE to find Total for all children
This recursive CTE (SQL Fiddle) should work with your sample:
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
;
Output
ParentID Count
1 6
2 3
3 2
4 1
Note: You mentioned in comments that the question only contains a simplified sample table and real data have proper indexes and handle duplicates and data adequately.
Data used (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)
;