2013-10-28 121 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中的乐趣,但也许你应该将所有相关的访问数据加载到您的应用程序中并确定应用程序中的用户级别?

我敢打赌,这将导致更多的可维护代码..