0

我有一个表引用自己。

用户表:id, username, manageridmanagerid链接回id

现在,我想得到所有的经理,包括直接经理,直接经理的经理等等......问题是我不想有一个不间断的递归sql。

所以,我想检查一个 id 是否已经在列表中,我将不再包含它。

这是我的sql:

with        
    all_managers (id, username, managerid, idlist) as
    (
        select u1.id, u1.username, u1.managerid, ' '
        from users u1, users u2
        where u1.id = u2.managerid
        and u2.id = 6

        UNION ALL

        select u.id, u.username, u.managerid, idlist + ' ' + u.id
        from all_managers a, users u
        where a.managerid = u.id
        and charindex(cast(u.id as nvarchar(5)), idlist) != 0
    )   
select id, username
from all_managers;

问题是在这一行:

select u1.id, u1.username, u1.managerid, ' '

SQL Server 向我抱怨我不能将 ' ' 作为 idlist 的初始化值。nvarchar(40) 也不能正常工作。我不知道如何在像这样的公用表表达式中声明它。通常,在 db2 中,我可以只放 varchar(40)

我的样本数据:

ID  UserName  ManagerID

1   admin     1
2   a         1
3   b         1
4   c         2

我想做的是找到c guy的所有经理。结果应该是:admin,a,b。

一些用户可以是他的经理(如管理员),因为 ManagerID 不允许为 NULL,而一些用户没有直接经理。

使用公共表表达式,它可以导致无限递归。所以,我也试图通过不包含两次 id 来避免这种情况。例如,在第 1 次迭代中,我们已经有了 id : 1,因此,在第 2 次及以后的迭代中,永远不允许使用 1。

我还想问一下我目前的方法是否好,还有其他解决方案吗?因为如果我有一个层次结构很深的大数据库,我将不得不初始化一个大的 varchar 来保存它,它会消耗内存,对吧?

4

1 回答 1

2

解决选角问题很容易。您只需要将联合中的两个值都转换为相同的类型:

With
    all_managers (id, username, managerid, idlist) as
    (
        Sselect u1.id, u1.username, u1.managerid
            , Cast(' ' As varchar(40))
        From users As u1
            Cross Join users As u2
        Where u1.id = u2.managerid
            and u2.id = 6
        Union All
        Select u.id, u.username, u.managerid
            , Cast(Coalesce(idlist + ' ','') + Cast(u.id As varchar(10)) As varchar(40))
        From all_managers As a
            Cross Join users As u
        Where a.managerid = u.id
            and CharIndex(Cast(u.id as nvarchar(5)), idlist) != 0
    )   
Select id, username, idlist
From all_managers;

但是,我仍然不太确定您要达到的目标。你能向我们展示一些应该和不应该在结果集中返回什么的示例数据吗?

于 2010-05-01T17:14:00.343 回答