如何从以下查询中获取层次结构值?


8

我有一个名为的表Category,其中有一个名为的列CategoryID。同一张表中有一个引用列,称为fParentCategoryID

我需要用逗号分隔所有类别ID及其子类别ID。例如-如果父类别ID为10,而父类别ID为20,则我打印类别ID 20时,我需要同时打印1和10作为其父,并以逗号分隔。

我尝试了以下查询,但我得到NULLParChild专栏。请帮忙。

;WITH
  cteReports 
  AS
(
SELECT c.CategoryID,
       c.fParentCategoryID,
       [level] = 1,
       ParChild=cast(CAST(c.fParentCategoryID AS VARCHAR(200)) + ',' + CAST(c.CategoryID AS VARCHAR(200)) AS VARCHAR(MAX))
FROM   retail.Category c
WHERE c.fParentCategoryID is NULL
UNION ALL
SELECT c.CategoryID,
       c.fParentCategoryID,
       [level] + 1,
       ParChild = ParChild + ',' + CAST(c.CategoryID AS VARCHAR(200))
FROM   retail.Category c
        JOIN cteReports r
            ON  c.fParentCategoryID = r.CategoryID

)

SELECT *
FROM   cteReports cr 

使用此脚本创建并填充表。 (注意:问题正文的上限为30K。因此,我不得不使用pastebin复制您的代码并引用它)

Answers:


3

我能够使用您的示例数据来复制您的结果。

您的问题是,在递归CTE(第一个select语句)的“基本”情况下,您将获得fParentCategoryID为null的记录,并将fParentCategoryID强制转换为准备添加“子级”的字符列。但是,在此阶段,“字符串”仍为NULL值(尝试使用SELECT CAST(NULL AS VARCHAR(200))或类似方法)。

然后,第二个select语句尝试将其他字符串值附加到NULL,但是默认情况下,数据库选项“ concat null产生null”表示如果您尝试将任何内容连接到NULL值,那么您仍然只会得到NULL-而不是将其视为一个空字符串。

您可以为此查询设置CONCAT_NULL_YIELDS_NULL OFF,尽管已弃用该查询,并且最终将在SQL Server的未来版本中将其删除(因此,您不应该将其添加到生产代码中!)

更好的方法是在第一个select语句中,而不是将fParentCategoryID强制转换为字符串,而只是强制转换CategoryID-我们已经知道父级应该为空,因为它们是NULL。

SELECT c.CategoryID,
   c.fParentCategoryID,
   [level] = 1,
   ParChild=cast(CAST(c.CategoryID AS VARCHAR(200)) AS VARCHAR(MAX))
FROM   retail.Category c
WHERE c.fParentCategoryID is NULL

如果您的数据在该select语句中可能包含null和非null值的混合,则还可以在其周围使用ISNULL将所有null视为空字符串。

当您获得诸如“,461,464”之类的值时,它可能需要对它产生的ParChild值进行一些清理,因此您可能希望去除开头的逗号。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.