我们的业务是一个分层的销售员关系,有时称为全方位层。它的3深。
英文版:Salesman-A-tier有人在他们之下,我们称他们为推销员-B-tier,b-tier有推销员,他们是推销员-C-tier。
表:
id, name, agentId
1011, bob, 0
1012, jim, 1011
1013, tim, 1011
1014, sam, 1011
1015, dav, 1013
1016, kim, 1013
1017, sal, 1015
1018, vin, 1015
(ID是代理商的Id,名为agentId的字段是salesmans上游代理商)
我需要的是所有销售人员的名单(在这种情况下为bob或id = 1011),3层深。
我已经达到了2级,但在那之后受到了限制。 认为这是一个更好的方法,我看不到自己,我正在寻求帮助。
到目前为止我的sql:
从中选择c.id,c.name,c.agentId 销售人员s.agentId = 1011或 s.agentId =(从中选择ss.agentId 推销员ss,其中ss.id = s.agentid)
这让我有2层深,但我不能得到第三层。
任何帮助表示赞赏。 提前致谢, 马修
答案 0 :(得分:2)
如果您正在使用 SQL Server 2008 ,或者如果您可以使用SQL Server 2008 - HierarchyId ,则SQL Server 2008中的数据类型可以非常轻松地解决您的问题。请查看以下这些参考资料。
以下是HierarchyId如何存储 omni-tiered 信息的直观表示。 alt text http://magmainteractive.net/tutorials/image.axd?picture=WindowsLiveWriter/IntroductiontotheSQLServer2008HIERARCHYI_10473/image_thumb_3.png
答案 1 :(得分:1)
直接的SQL-92解决方案,避免递归(不是普遍实现)和特定于供应商的功能(出于通常的原因):
select
theAnswer.*
from
salesmen s0
join
salesmen s1 on s0.id in (s1.id, s1.agentId)
join
salesmen theAnswer on s1.id = theAnswer.agentId
where
0 = s0.agentId
and
1011 in (s0.id, s1.id)
这里的假设是感兴趣的销售人员(在这种情况下为id = 1011
)可以是A层或B层。要将查询限制为仅从A层开始的搜索,请将最后一行替换为:
1011 = s0.id
另一个假设是每个销售人员只有一行(id
是UNIQUE
),这意味着任何给定的销售人员只有一个agentId
。如果不是这样,请将第一行替换为:
select distinct
我应该指出,样本数据中有四个层,而不是问题陈述中的三个层。
bob
jim
,tim
,sam
dav
,kim
sal
,vin
在这种情况下,原始查询变为:
select
theAnswer.*
from
salesmen s0
join
salesmen s1 on s0.id in (s1.id, s1.agentId)
join
salesmen s2 on s1.id in (s2.id, s2.agentId)
join
salesmen theAnswer on s2.id = theAnswer.agentId
where
0 = s1.agentId
and
1011 in (s0.id, s1.id, s2.id)
and
(s0.id = s1.id or s1.id <> s2.id)
最后一行的目的是避免将查询转换为select distinct
,而只是减少:
(
s0.id = s1.id and s1.id = s2.id
or
s0.id = s1.id and s1.id <> s2.id
or
s0.id <> s1.id and s1.id <> s2.id
)
要获得5级层次结构,只需比较第一个和第二个查询即可看到模式出现。
FROM
子句获得额外的JOIN
。JOIN
必须与此新JOIN
进行比较。WHERE
子句的第二部分获取额外项目。WHERE
子句的最后一部分建立在上面未简化的代码段上,添加了一个额外的OR
条件来处理对新JOIN
的额外比较,遵循由=
和<>
运营商。答案 2 :(得分:0)
这里一个简单的选择是使用递归CTE。确保用分号完成前一个语句。
with recCTE as
(
/* Base case first */
SELECT 1 as theLevel, *
FROM theTable
WHERE AgentID = 0
/* Recurisve bit */
UNION ALL
SELECT r.theLevel + 1, t.*
FROM recCTE r
JOIN theTable t
ON r.ID = r.AgentID
)
SELECT *
FROM recCTE
WHERE theLevel <= 3;
答案 3 :(得分:0)
我知道重新架构这样的表通常很痛苦(或几乎不可能),但如果这是一个选项,那么你应该在SQL中查看Joe Celko's book on trees and hierarchies。他有一些替代表设计,比如嵌套集模型,它可以使你的查询变得微不足道。 Here's我可以从Google找到的一个简短示例。
除非重新设计,否则如果您使用的是MS SQL Server 2005或更高版本,则可以使用CT建议。我不知道其他RDBMS可能提供的递归函数(如果有的话)。