SQL Server递归CTE查询,以查找属于所有类别及其后代的所有项目

时间:2015-10-28 10:30:13

标签: sql sql-server tsql

我有点困惑,试图使用递归CTE列出产品目录中所有类别的所有项目各个项目所属的各自父类别。

表格非常简单......

  • Category;列:Id,ParentID,Title
  • itemCategory;列:ItemID,CategoryID

我正在努力研究如何获得我想要的结果。我最好的尝试是不对的:

WITH
CTE (itemID, categoryID, title) AS (
    SELECT itemID, categoryID, title
    FROM itemcategory
    INNER JOIN category ON category.ID = itemcategory.categoryID
    UNION ALL
    SELECT iI.ItemID, iI.categoryID, i.title
    FROM itemcategory iI INNER JOIN category i ON i.ID = iI.categoryID
    INNER JOIN CTE ON CTE.categoryID = i.ParentID)
SELECT * FROM CTE

我有一个类似的查询,它计算每个类别下的项目数:

WITH cte_count_category(id, parentid, c)
        AS (SELECT c1.id,
                c1.parentid,
                (SELECT Count(*)
                    FROM   (SELECT DISTINCT itemid
                            FROM   itemcategory AS iI
                            WHERE  iI.categoryid = c1.id) AS t1) AS c
            FROM   category AS c1
            UNION ALL
            SELECT c2.id,
                c2.parentid,
                d.c
            FROM   category c2
                INNER JOIN cte_count_category d
                        ON c2.id = d.parentid)
SELECT cte_count_category.id,
        cte_count_category.parentid,
        title,
        Sum(c)     itemCount
FROM   cte_count_category
        LEFT JOIN category
                ON category.id = cte_count_category.id
GROUP  BY cte_count_category.id,
            cte_count_category.parentid,
            title
HAVING Sum(c) > 0
ORDER  BY itemcount DESC;

我无法弄清楚如何让它列出所有项目。任何帮助将不胜感激。

编辑:类别需要很深,尽管大多数时候它不太可能超过4个级别。

我正在寻找的输出是每个类别ID为一行,因此,“音乐书”类别中的项目将出现在“音乐书”类别和“书籍”类别下。

1 个答案:

答案 0 :(得分:2)

我认为您需要的逻辑会被项目混淆。你在CTE中实际上并不需要它们(你可以在之后加入它们)。或者,您可以将它们放在" base"构造的一部分。递归部分只需要类别。

这可能是您正在寻找的:

WITH CTE (itemID, categoryID, title, parentid, lev) AS (
      SELECT ic.itemID, c.categoryID, c.title, c.parentid, 0
      FROM itemcategory ic INNER JOIN
           category c
           ON c.ID = ic.categoryID
      UNION ALL
      SELECT cte.ItemID, c.categoryID, c.title, c.parentid, cte.lev + 1
      FROM CTE INNER JOIN
           category c
           ON CTE.ParentID = c.categoryID
     )
SELECT * FROM CTE