【问题标题】:Recursive SQL Query, but not the usual kind of recursive递归 SQL 查询,但不是通常的递归类型
【发布时间】:2013-07-06 03:34:48
【问题描述】:

我有一组表格,可以将一组人组织成团队。

  • 用户(ID int PK 等)
  • 团队(ID int PK 等)
  • UsersToTeams(ID int PK、UserID int FK、TeamID int FK、TeamSupervisor 位不为空)

表中没有父 ID,因为用户可以加入任意数量的团队,并且团队可以有任意数量的主管。一个用户可能在六个团队中,但只监督其中两个,而这些受监督团队中的一个或两个可能有其他监督者。所以我的层次结构看起来更像是一张网络而不是一棵树。

我知道递归查询可能会导致循环引用。假设该软件目前正在处理该问题。

公司层次结构由监督用户团队的主管、监督主管团队的经理等描述。所以它是层次结构的,但不是通常的方式。

我需要一个查询,给定一个 UserID,它将返回他所监督的用户的 ID,向下无限级别。这样的查询会如何进行?

例子

Users (ID, Name)
1 Archie
2 Betty
3 Chuck
4 Dilton
5 Eddie
6 Fannie

用户 1 是经理(级别 3)。用户 2 和 3 是主管(2 级)。用户 4、5、6 是用户(1 级)。

Teams (ID, Name)
1 Team Alpha
2 Team Bravo
3 Sup Team

UsersToTeams (ID INT PK, UserID INT FK, TeamID INT FK, isSupervisor BIT)
1 1 3 1  -- Archie supervises Sup Team
2 2 3 0  -- Betty is a member of Sup Team
3 3 3 0  -- Chuck is a member of Sup Team
4 2 1 1  -- Betty supervises team Alpha
5 4 1 0  -- Dilton is a member of team Alpha
6 5 1 0  -- Eddie is a member of team Alpha
7 3 2 1  -- Chuck supervises Team Bravo
8 6 2 0  -- Fannie is a member of Team Bravo
  • Archie 是一名经理,负责监督一个主管团队。
  • Betty 是一名主管,负责监督一组用户。
  • Chuck 是一名主管,负责监督一组用户。
  • Betty 和 Chuck 在 Archie 的团队中,但不要监督它。

因此:

  1. 如果我传入 UserID 5 (Eddie),我应该只返回 5,因为 Eddie 不监督任何人。
  2. 如果我传入 UserID 3 (Chuck),我应该返回 3 和 6,因为 Fannie 在 Chuck 监督的团队中。
  3. 如果我传入 UserID 1 (Archie),我应该取回此处描述的所有 UserID,因为 Betty 和 Chuck 在 Archie 的团队中,而其他所有人都在 Betty 的团队或 Chuck 的团队中。

抱歉,我尝试了那个 SQL 小提琴链接,但在“构建架构”15 分钟后,我对它失去了希望。

【问题讨论】:

  • 你能设置一些示例数据吗?你可以使用sqlfiddle.com/#!6
  • 以及预期的结果集以及样本数据
  • 也许这会有所帮助,它似乎是对您想要做什么的彻底解释:blog.sqlauthority.com/2012/04/24/…
  • 按要求添加了示例数据。 SqlFiddle 从未完成架构的构建。

标签: sql sql-server recursion recursive-query


【解决方案1】:

您可以使用递归 CTE 来做到这一点。

首先,选择用户自己,然后递归地选择他立即监管的所有用户:

declare @userID int = 1;

with u as (
  select id from users where id = @userID
  union all
  select lacky.userID from u supervisor
  join usersToTeams supervising on supervising.userID = supervisor.id and isSupervisor = 1
  join usersToTeams lacky on lacky.teamID = supervising.teamID and lacky.isSupervisor = 0
)

select * from u

这是小提琴:http://www.sqlfiddle.com/#!3/525e1/3

【讨论】:

  • 谢谢。顺便说一句,这似乎是一种糟糕的设计方式。不完全是 1NF。关于更好的布局有什么想法吗?
  • @tsilb 抱歉,我对正常形式了解不多。我只是让它工作。 =D 你的架构对我来说看起来很不错。我可能做的唯一更改是以下之一:1. 删除 UsersToTeams.ID 并将主键更改为 (UserID, TeamID) 或 2. 应用唯一性约束以确保用户两次不在同一个团队中。
猜你喜欢
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
  • 2015-07-13
  • 2014-12-19
  • 2012-12-05
  • 2016-01-25
  • 1970-01-01
相关资源
最近更新 更多