7

我对这个递归 CTE 有一点问题,它工作得很好,除非我有一个没有 root 可读权限的用户意味着这个元素没有条目。因此,如果我对仅在树内的叶子上具有权限的用户运行此查询,则此查询的级别部分将无法正常工作。

它将显示示例 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

当用户现在只有对 id 8 和 9 的读取权限时,来自 CTE 的级别对于 id 8 和 3 对于 id 9 保持在 2,但如果之前没有人,我需要 id 8 级别 1

4

6 回答 6

2

您还没有告诉我们您是如何知道用户是否拥有给定 ID 的权限的。这是一个必要的信息。我将在下面放置一些代码,假设您在查询中添加一个名为hasRights的列,并且如果用户没有权限,则该列的值为零,如果有,则该列的值为零。您可能需要对此进行调整,因为我没有要测试的数据,但希望它能让您接近。

基本上,如果用户有权限,查询会更改为仅将级别加 1。如果用户有权限,它也只会添加到排序路径,否则会附加一个空字符串。因此,如果 id 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
于 2013-11-06T16:46:17.063 回答
0

如果更高级别(0 或 1 )不存在,则您需要类似的东西,那么下一个级别将成为更高级别..

如果是,那么您必须在最终结果时执行此操作

在临时表中插入所有结果让我们说#info(具有相同的数据特​​征)

现在在表格中准备好所有最终数据之后,

请从顶部检查。

选择 * from #info where level= 0

如果这返回 0 行,那么您必须更新每个记录级别。到(级别 = 级别 -1)

现在再次对 Level=0,然后是 level 1,然后是 level 2,然后是 level 3 进行递归。这将很容易但不容易编码。所以尝试不递归,然后尝试最终更新。

我希望这个能帮上忙 :)

如果您正在寻找其他东西,请回复。

于 2013-11-05T11:23:08.920 回答
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
于 2013-11-05T21:58:18.283 回答
0

将表转换为分层类型是一种选择:

或者

  • xml数据类型
于 2013-12-09T09:33:46.620 回答
0

有时选项(最大递归 10000);非常有用
我没有时间阅读你的问题,但这里剪断了

declare cursorSplit Cursor for
   select String from dbo.SplitN(@OpenText,'~') 
   where String not in (SELECT [tagCloudStopWordText]     
   FROM [tagCloudStopList] where [langID]=@_langID)
   option (maxrecursion 10000);
open cursorSplit
于 2013-12-09T21:55:47.723 回答
0

我很抱歉成为一个派对大佬,破坏了创建如此有趣的 SQL 的乐趣,但也许您应该将所有相关的访问数据加载到您的应用程序中并确定应用程序中的用户级别?

我敢打赌它会导致更可维护的代码..

于 2014-04-14T14:07:55.207 回答