2017-07-25 71 views
1

我想获取所有祖先,所选类别和直接子项,并计算每个类别及其所有子项中的所有项目。如何在此sql查询中获取所有祖先,所选类别和直接子项

这是我做过什么:

DECLARE @CategoryId INT = 8 
;WITH Re AS 
(
SELECT CategoryId, Name, ParentId, CategoryId RootId, 0 Depth, Sort = CAST(Name AS VARCHAR(MAX)) 
    FROM Category 
WHERE CategoryId = @CategoryId OR ParentId = @CategoryId 
UNION ALL 
SELECT C.CategoryId, C.Name, C.ParentId, RootId, Depth = Re.Depth + 1, Sort = Re.Sort + CAST(C.Name AS VARCHAR(200)) 
    FROM Re JOIN Category C ON Re.CategoryId = C.ParentId 
) 
SELECT Y.CategoryId, Y.Name, Y.ParentId, X.CatCount 
    FROM (SELECT RootId, COUNT(I.CategoryId) catCount 
      FROM Re LEFT OUTER JOIN Item I ON Re.CategoryId = I.CategoryId 
      GROUP BY RootId) X 
    JOIN (SELECT Re.CategoryId, Re.ParentId, Name, MAX(Depth) MaxDepth 
      FROM Re 
      GROUP BY Re.CategoryId, Re.ParentId, Name) Y ON Y.CategoryId = X.RootId 
ORDER BY CategoryId 

返回我想要什么,但有一点问题是它。例如当@CategoryID = 8,此查询应显示:

CategoryId Name ParentId CatCount 
    0  A  NULL   16 
    1  B   0   10 
    7  H   1   4 
    8  I   7   2 
    13  N   8   1 

但它返回:当选择子类别

CategoryId Name ParentId CatCount 
    8  I   7   2 
    13  N   8   1 

祖先未示出。

  1. 问题在哪里?
  2. 如何优化此查询?

我会感谢另外一个人帮助我

+0

你是什么样的输入数据? –

+0

在此查询或我的某个表中输入样本数据? – Masoud

+0

对于那个预期产出 –

回答

0

您的查询不象你所说的,因为与RootId问题(见下文评论) 你的CTE需要改变这个工作的:

DECLARE @CategoryId INT = 8 
;WITH Re AS 
(
    -- Anchor (this is the starting category) 
    SELECT CategoryId, Name, ParentId, CategoryId AS RootId, 
     0 AS Depth, Sort = CAST(Name AS VARCHAR(MAX)), CONVERT(VARCHAR(20), 'Root') AS Relation 
    FROM Category 
    WHERE CategoryId = @CategoryId 
    UNION ALL 
    -- Find children 
    SELECT C.CategoryId, C.Name, C.ParentId, C.CategoryId AS RootId, -- Fixed RootId problem 
     Depth = Re.Depth + 1, Sort = Re.Sort + CAST(C.Name AS VARCHAR(200)), CONVERT(VARCHAR(20), 'Child') AS Relation 
    FROM Re 
     INNER JOIN Category C ON Re.CategoryId = C.ParentId 
    WHERE Re.Relation IN('Root', 'Child') 
     -- I do not think this is necessary as we have established the anchor, see above 
     AND C.ParentId = @CategoryId 
    UNION ALL 
    -- Find Ancestors (Parents) 
    SELECT C.CategoryId, C.Name, C.ParentId, C.CategoryId AS RootId, -- Fixed RootId problem 
     Depth = Re.Depth - 1, Sort = Re.Sort + CAST(C.Name AS VARCHAR(200)), CONVERT(VARCHAR(20), 'Parent') AS Relation 
    FROM Re 
     INNER JOIN Category C ON C.CategoryId = Re.ParentId 
    WHERE Re.Relation IN('Root', 'Parent') 
) 
SELECT * FROM Re 

我已经使用了以下数据:

CREATE TABLE Category(CategoryId INT, Name VARCHAR(10), ParentID INT) 
SELECT * FROM Category 
INSERT INTO Category 
SELECT 0, 'A', NULL UNION ALL 
SELECT 1 , 'B', 0 UNION ALL 
SELECT 7 , 'H' , 1 UNION ALL 
SELECT 8 , 'I' , 7 UNION ALL 
SELECT 13 , 'N' , 8 
-- DROP TABLE Category 
+0

非常感谢。它工作正常。我改变了WHERE Re.Relation IN('Root','Child')到WHERE Re.Relation IN('Root','Child')和C.ParentId = @CategoryId,现在它正是我想要的。 – Masoud

+0

@Masoud - 我不确定你是否需要它。无论如何,我的示例运行良好。 – Alex

+0

我正在寻找所有的父母,只是直接选择categoryId的孩子。你的查询效果很好,并且想知道我的意思,但是它返回的是所有8的孩子,而不是它的直接孩子例如,如果13有一个孩子,@CategoryId = 8,它返回13和它的孩子,这是不需要的。但该解决方案对我非常有用,非常感谢。 – Masoud

相关问题