2013-10-28 6 views
6

Ich habe ein kleines Problem mit diesem rekursiven CTE, es funktioniert gut, außer wenn ich einen Benutzer ohne root lesbare Rechte habe bedeutet, keinen Eintrag für dieses Element. Wenn ich diese Abfrage für einen Benutzer mit Rechten nur auf den Blättern in der Struktur ausführen, wird der Ebenenteil dieser Abfrage nicht korrekt funktionieren.Rekursive Cte ​​sql mit für Hierarchieebene

zeigt es die reale Ebene Hierarchie zum Beispiel 6, aber es ist das obere erste lesbare Element für ihn so sollte es 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 

das Niveau sein wird wie folgt

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

Wenn ein Benutzer jetzt nur Leserechte auf ID 8 und 9 hat, bleibt die Stufe von CTE 2 für ID 8 und 3 für ID 9, aber ich brauche für ID 8 Stufe 1, wenn niemand vor

+0

Können Sie einige Daten und erwartete Ergebnisse zeigen? – Kaf

+0

der Pegel ist wie folgt: id, Ebene 5, 0 2, 1 7, 2 4, 2 1, 2 6, 1 3, 2 8, 2 9, 3 wenn ein user hat jetzt nur leserechte an id 8 und 9 das level von cte bleibt bei 2 für id 8 und 3 für id 9 aber ich brauche für id 8 level 1 wenn es noch keinen gibt – Mikatsu

+0

thx für die hind aktualisiert jetzt – Mikatsu

Antwort

2

Sie haben uns nicht gesagt, wie Sie wissen, ob ein Benutzerrechte auf eine bestimmte ID hat. Das ist eine notwendige Information. Ich werde einen Code unterhalb setzen, der davon ausgeht, dass Sie Ihrer Abfrage eine Spalte namens hasRights hinzufügen und dass diese Spalte einen Wert von Null haben wird, wenn der Benutzer keine Rechte und einen Wert von eins hat, wenn sie dies tun. Möglicherweise müssen Sie dies optimieren, da ich keine Daten zum Testen habe, aber hoffentlich wird es Ihnen nahe kommen.

Grundsätzlich wird die Abfrage so geändert, dass nur 1 zur Ebene hinzugefügt wird, wenn der Benutzer Rechte hat. Es fügt auch nur dem Sortierpfad hinzu, wenn der Benutzer Rechte besitzt, andernfalls wird eine leere Zeichenfolge angehängt. Also, wenn IDs 8 und 9 die einzigen Elemente sind, auf die der Benutzer zugreifen kann, sollten Sie Ebenen von 1 und 2 sehen und Pfade ähnlich wie '5/8/9' statt '5/6/8/9' sortieren. Wenn Sie immer noch nicht in der Lage sind, es zum Laufen zu bringen, würde es uns enorm helfen, wenn Sie ein Beispielschema auf SqlFiddle gepostet haben.

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

Sie vergelten so etwas wie, wenn das höhere Niveau (0 oder 1) nicht existiert, dann ist die nächste Stufe der höheren Ebene werden ..

Wenn ja, dann müssen Sie dies tun, wenn das Endergebnis

alle Ergebnisse in temporäre Tabelle einfügen #info können sagen (mit gleichen Eigenschaften der Daten)

Jetzt, nachdem alle endgültigen Daten bereit, in der Tabelle,

von oben Bitte überprüfen Sie.

Select * from #info wo level = 0

wenn diese 0 Zeilen zurückgibt, dann müssen Sie die einzelnen Datensätze Ebene aktualisieren. to (level = level -1)

Nun wieder gleich für Level = 0, dann Level 1, dann Level 2, dann Level 3 in Rekursion. Das wird einfach, aber nicht einfach zu programmieren sein. Versuchen Sie also ohne Rekursion und versuchen Sie dann das letzte Update.

Ich hoffe, das wird helfen :)

Bitte antworten Sie, wenn Sie nach etwas anderem suchen sind.

0

Versuchen Sie, die folgende select ausführen und lassen Sie mich wissen, ob es das gewünschte Ergebnis ist:

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

Option einige Zeit (maxrecursion 10000); sehr nützlich ist
ich Ihr Problem keine Zeit haben, zu lesen, aber hier 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

Es tut mir Leid ein Spielverderber zu sein und Spaß zu schaffen, so ein interessantes Stück von SQL, verderben aber vielleicht Sie sollten Sie alle relevanten Zugangsdaten in Ihre Anwendung laden und die Benutzerebenen in der Anwendung ermitteln?

Ich wette, es würde in mehr wartbaren Code führen ..