Como posso obter os valores hierárquicos da consulta abaixo?

8

Eu tenho uma tabela chamada Categoryque tem uma coluna chamada CategoryID. Há uma coluna de referência na mesma tabela chamada fParentCategoryID.

Eu preciso obter todos os IDs de categoria e seus IDs de subcategoria separados por vírgula. Por exemplo - se o ID da categoria pai de 10 for 1 e se o ID da categoria pai de 20 for 10, quando eu imprimir o ID da categoria 20, preciso imprimir 1 e 10 como seus pais em valores separados por vírgula.

Eu tentei a consulta abaixo, mas recebo NULLa ParChildcoluna. Por favor ajude.

;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 

use este script para criar e preencher a tabela. (nota: há um limite de 30K para o corpo da pergunta. Então, eu tive que usar o pastebin para copiar seu código e fazer referência a ele)

mayooran
fonte

Respostas:

3

Consegui replicar seus resultados com seus dados de exemplo.

Seu problema é que, no caso "base" do CTE recursivo (a primeira instrução de seleção), você está obtendo os registros em que fParentCategoryID é nulo e convertendo o fParentCategoryID em uma coluna de caracteres pronta para acrescentar os "filhos". No entanto, a 'string' ainda é um valor NULL neste estágio (tente com SELECT CAST (NULL AS VARCHAR (200)) ou algo semelhante).

A segunda instrução select tenta anexar outros valores de seqüência de caracteres ao NULL, mas, por padrão, a opção do banco de dados "concat null produz null" diz que se você tentar concatenar algo para um valor NULL, você ainda obterá NULL - em vez de tratá-lo como uma string vazia.

Você pode SET CONCAT_NULL_YIELDS_NULL OFF para esta consulta, embora isso tenha sido descontinuado e acabe sendo removido em uma versão futura do SQL Server (portanto, você provavelmente não deve adicioná-lo ao código de produção!)

Uma maneira melhor é na primeira instrução select, em vez de converter o fParentCategoryID em uma string, basta converter o CategoryID - já sabemos que o pai deve estar vazio, pois são os NULLs.

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

Se seus dados puderem ter uma mistura de valores nulos e não nulos nessa instrução de seleção, você também poderá usar ISNULL ao redor dele para tratar quaisquer nulos como cadeias vazias.

Provavelmente precisa de alguma limpeza no valor ParChild que produz à medida que você obtém valores como ", 461.464", portanto, você pode querer retirar a vírgula inicial.

seventyeightist
fonte