2013-10-28 10 views
6

Ho un piccolo problema con questo CTE ricorsivo, funziona bene tranne quando ho un utente senza diritti di root readable significa nessuna voce per questo elemento. Quindi, se eseguo questa query su un utente con diritti solo sulle foglie all'interno dell'albero, la parte del livello di questa query non funzionerà correttamente.cq sql ricorsivo con per livello gerarchico

mostrerà il vero livello di gerarchia ad esempio 6 ma il suo il primo elemento leggibile in alto per lui, così dovrebbe essere 1.

WITH Tree 
AS (
SELECT 
    id, 
    parent, 
    0 AS Level, 
    id AS Root, 
    CAST(id AS VARCHAR(MAX)) AS Sort, 
    user_id 
FROM SourceTable 
WHERE parent IS NULL 

UNION ALL 

SELECT 
    st.id, 
    st.parent, 
    Level + 1 AS Level, 
    st.parent AS Root, 
    uh.sort + '/' + CAST(st.id AS VARCHAR(20)) AS Sort, 
    st.user_id 
FROM SourceTable AS st 
    JOIN Tree uh ON uh.id = st.parent  
) 

SELECT * FROM Tree AS t 
    JOIN UserTable AS ut ON ut.id = t.user_id AND ut.user_id = '141F-4BC6-8934' 
ORDER BY Sort 

il livello è la seguente

id level 
5 0 
2 1 
7 2 
4 2 
1 2 
6 1 
3 2 
8 2 
9 3 

Quando un utente ora ha solo i diritti di lettura su id 8 e 9 il livello da CTE rimane a 2 per id 8 e 3 per id 9 ma ho bisogno di id 8 livello 1 se non c'è nessuno prima

+0

Puoi mostrare alcuni dati e risultati attesi? – Kaf

+0

il livello è il seguente id, livello 5, 0 2, 1 7, 2 4, 2 1, 2 6, 1 3, 2 8, 2 9, 3 quando un l'utente ora ha solo i diritti di lettura di id 8 e 9 il livello da cte rimane a 2 per id 8 e 3 per id 9 ma ho bisogno di id 8 livello 1 se non c'è nessuno prima – Mikatsu

+0

thx per l'hind aggiornato di conseguenza ora – Mikatsu

risposta

2

Non ci hanno detto come sapere se un utente dispone dei diritti ad un dato id. Questa è un'informazione necessaria. Inserirò un codice sotto che presuppone l'aggiunta di una colonna alla query denominata hasRights e che questa colonna avrà un valore zero se l'utente non ha diritti e il valore di uno se lo fa. Potrebbe essere necessario modificare questo, dal momento che non ho dati da testare, ma si spera che ti avvicini.

In sostanza, la query viene modificata per aggiungere solo 1 al livello se l'utente dispone di diritti. Inoltre aggiunge solo al percorso di ordinamento se l'utente ha diritti, altrimenti viene aggiunta una stringa vuota. Pertanto, se gli ID 8 e 9 sono gli unici elementi a cui l'utente può accedere, dovresti visualizzare i livelli 1 e 2 e ordinare i percorsi in modo simile a "5/8/9" anziché "5/6/8/9". Se ancora non sei in grado di farlo funzionare, ci aiuterebbe moltissimo se pubblichi uno schema di esempio su SqlFiddle.

WITH Tree 
AS (
SELECT 
    id, 
    parent, 
    0 AS Level, 
    id AS Root, 
    hasRights AS HasRights, 
    CAST(id AS VARCHAR(MAX)) AS Sort, 
    user_id 
FROM SourceTable 
WHERE parent IS NULL 

UNION ALL 

SELECT 
    st.id, 
    st.parent, 
    Level + st.hasRights AS Level, 
    st.parent AS Root, 
    st.hasRights AS HasRights, 
    uh.sort + CASE st.hasRights WHEN 0 THEN '' ELSE '/' + CAST(st.id AS VARCHAR(20)) END AS Sort, 
    st.user_id 
FROM SourceTable AS st 
    JOIN Tree uh ON uh.id = st.parent  
) 

SELECT * FROM Tree AS t 
    JOIN UserTable AS ut ON ut.id = t.user_id AND ut.user_id = '141F-4BC6-8934' 
ORDER BY Sort 
0

È ricambiare qualcosa di simile se il livello più alto (0 o 1) non è in atto, allora il livello successivo diventare il più alto livello ..

Se sì, allora si deve fare questo quando il risultato finale

inserire tutti i risultati nella tabella temporanea permette di dire #info (con le stesse caratteristiche dei dati)

Ora, dopo tutti i dati definitivi pronto in tavola,

si prega di controllare dall'alto.

Select * from #info dove il livello = 0

se restituisce 0 righe, allora è necessario aggiornare ogni livello record. a (livello = livello -1)

Ora di nuovo uguale per Livello = 0, quindi livello 1, quindi livello 2, quindi livello 3 in ricorsione. questo sarà facile ma non facile da codificare. Quindi prova senza ricorsione, quindi prova l'aggiornamento finale.

Spero che questo vi aiuterà :)

preghiamo di rispondere se siete alla ricerca di qualcosa di diverso.

0

tenta di eseguire il seguente selezionare e fatemi sapere se è il risultato desiderato:

SELECT *, 
DENSE_RANK() OVER (PARTITION BY t.user_id ORDER BY t.LEVEL ASC) -1 as RelativeUserLevel 
FROM Tree AS t 
    JOIN UserTable AS ut ON ut.id = t.user_id AND ut.user_id = '141F-4BC6-8934' 
ORDER BY Sort 
0

opzione ALCUNE VOLTE (maxrecursion 10000); è molto utile
non ho il tempo di leggere il vostro problema, ma qui snipped

declare cursorSplit Cursor for 
    select String from dbo.SplitN(@OpenText,'~') 
    where String not in (SELECT [tagCloudStopWordText]  
    FROM [tagCloudStopList] where [langID][email protected]_langID) 
    option (maxrecursion 10000); 
open cursorSplit 
0

Mi dispiace di essere un guastafeste e rovinare il divertimento di creare un tale pezzo interessante di SQL, ma forse voi dovrebbe caricare tutti i dati di accesso rilevanti nell'applicazione e determinare i livelli utente nell'applicazione?

Scommetto che risulterebbe in un codice più gestibile ..

Problemi correlati