2013-10-28 78 views
6

我有這個遞歸CTE的一個小問題,它工作正常,除非我有一個沒有根可讀權限的用戶意味着沒有這個元素的條目。因此,如果我在樹中的葉子上使用權限的用戶運行此查詢,此查詢的級別部分將無法正常工作。遞歸cte sql與層次級別

它將顯示出真實的水平層次結構例如6但對他來說其頂端第一可讀元件所以它應該是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 

水平如下

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

當用戶現在只擁有閱讀權8和9時,CTE的等級爲2,id 8爲3,但是如果之前沒有人,我需要id 8等級1

+0

你能顯示一些數據和預期的結果嗎? – Kaf

+0

水平如下 ID, 水平5,0 2,1 7,2 4,2 1,2 6,1 3,2 8,2 9,3 當用戶現在只有閱讀權利ID 8和9從cte的水平停留在2爲id 8和3爲id 9,但我需要爲id 8級別1,如果之前沒有人 – Mikatsu

+0

thx爲後來更新相應現在 – Mikatsu

回答

2

你還沒告訴我們你是怎麼知道用戶是否有權給定的ID。這是一個必要的信息。假設您在查詢中添加了一列名爲hasRights的列,並且如果用戶沒有權限,那麼此列將具有零值,如果他們具有值,則該列將具有一個值。你可能需要調整它,因爲我沒有數據可以測試,但希望它能讓你接近。

基本上,如果用戶有權限,則查詢將被更改爲僅將1添加到級別。如果用戶擁有權限,它也只會添加到排序路徑中,否則會附加一個空字符串。因此,如果ids 8和9是用戶可以訪問的唯一項目,則應該看到1和2級別,並對路徑進行排序,類似於「5/8/9」而非「5/6/8/9」。如果你仍然無法實現它,那麼如果你在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

你報答類似,如果更高級別(0或1)不存在,那麼一個新的水平變得更高水平..

如果是的話,那麼你必須要做到這一點時,最終的結果

插入臨時表中所有的結果讓說#info(有數據的相同特徵)

現在,經過表中的所有最終的數據準備,

請從頂部檢查。

從#info其中level = 0

如果它返回0行,那麼你必須更新每個記錄水平

選擇*。到(level = level -1)

現在對於Level = 0又是相同的,然後是level 1,然後是level 2,然後是遞歸級別3。這將很容易但不容易編碼。所以嘗試沒有遞歸,然後嘗試最終更新。

我希望這會有所幫助:)

如果您正在尋找別的東西,請回復。

0

嘗試執行以下選擇,讓我知道這是否是你想要的結果:

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

某些時間選項(maxrecursion 10000);是非常有用的
我沒有時間來閱讀你的問題,但在這裏剪斷

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

我很抱歉要掃大家的興,慣創建這樣一個有趣的SQL中的樂趣,但也許你應該將所有相關的訪問數據加載到您的應用程序中並確定應用程序中的用戶級別?

我敢打賭,這將導致更多的可維護代碼..