Come posso ottenere i valori gerarchici dalla query seguente?


8

Ho una tabella denominata Categoryche ha una colonna denominata CategoryID. C'è una colonna di riferimento nella stessa tabella chiamata fParentCategoryID.

Devo separare virgola tutti gli ID categoria e i relativi ID sottocategoria. Ad esempio, se l'ID categoria padre di 10 è 1 e se l'ID categoria padre di 20 è 10, quando stampo l'ID categoria 20, devo stampare sia 1 che 10 come suoi genitori in valori separati da virgola.

Ho provato la query qui sotto ma ottengo NULLper la ParChildcolonna. Per favore aiuto.

;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 

utilizzare questo script per creare e popolare la tabella. (nota: c'è un limite di 30K al corpo della domanda .. Quindi ho dovuto usare pastebin per copiare il tuo codice e fare riferimento a esso)

Risposte:


3

Sono stato in grado di replicare i tuoi risultati con i tuoi dati di esempio.

Il problema è che nel caso "base" del CTE ricorsivo (la prima istruzione select) si ottengono i record in cui fParentCategoryID è nullo e si esegue il casting di fParentCategoryID in una colonna di caratteri pronta ad aggiungere i "figli". Tuttavia, la 'stringa' è ancora un valore NULL in questa fase (provalo con SELECT CAST (NULL AS VARCHAR (200)) o simili).

La seconda istruzione select tenta quindi di aggiungere altri valori di stringa al NULL ma, per impostazione predefinita, l'opzione di database "concat null nulls null" dice che se si tenta di concatenare qualcosa a un valore NULL, si ottiene comunque NULL, anziché trattarlo come una stringa vuota.

È possibile IMPOSTARE CONCAT_NULL_YIELDS_NULL OFF per questa query sebbene sia obsoleto e alla fine verrà rimosso in una versione futura di SQL Server (quindi probabilmente non dovresti aggiungerlo al codice di produzione!)

Un modo migliore è nella prima istruzione select, invece di lanciare fParentCategoryID su una stringa, basta semplicemente lanciare il CategoryID: sappiamo già che il genitore dovrebbe essere vuoto in quanto sono i 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

Se i tuoi dati potrebbero avere una combinazione di valori null e non null in quell'istruzione select, puoi anche usare ISNULL attorno ad essi per trattare tutti i null come stringhe vuote.

Probabilmente ha bisogno di un po 'di pulizia sul valore di ParChild che produce quando ottieni valori come ", 461.464", quindi potresti voler eliminare la virgola iniziale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.