2009-12-24 68 views
1

我們的業務是分層銷售人員關係,有時也稱爲全層。它3深。從單個表格中提取3層相關數據

用英語:Salesman-A-tier有他們下的人,我們稱他們爲推銷員-B-層,而B-tier在他們的推銷員C-層中有推銷員。

表:

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是代理的標識,被稱爲的agentId領域是salesmans上游劑)

我需要的是在所有這一切下的推銷員的列表(案例鮑勃或編號= 1011),3層深。

我已經得到了2級的深度,但之後得到了抑制。 找到一個更好的方法我看不到我自己,我尋求幫助。

我的SQL至今:

選擇c.id,c.name,c.agentId從 推銷員S其中s.agentId = 1011或 s.agentId =(從 選擇ss.agentId推銷員ss其中ss.id = s.agentid)

這讓我2層深,但我不能得到第三。

任何幫助表示讚賞。 在此先感謝, 馬修

+1

這不能解決你的問題,但你真的應該考慮規範化你的表,這樣你就不必爲這樣簡單的數據做枯燥乏味的查詢。 拔出業務代表id並製作一個只有id和業務代表id的表。 – 2009-12-24 01:59:10

+1

這是幹什麼用的數據庫? – 2009-12-24 02:25:24

回答

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; 
0

我知道,這往往是一個痛苦(或幾乎是不可能的)重新構建一個表像,但如果這是一個選項,那麼你應該在SQL退房Joe Celko's book on trees and hierarchies。他有一些可供選擇的表格設計,例如嵌套集合模型,它可以使您的查詢變得瑣碎。 Here's我能從Google找到的一個簡單示例。

除非重新設計,如果你在MS SQL Server 2005或更高,那麼你可以使用熱膨脹係數爲羅布建議是。我不知道其他RDBMS可能提供的遞歸函數(如果有的話)。

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 

另一個假設是,有每個銷售人員的具體哪一行(idUNIQUE),這意味着任何給定的銷售人員有一個agentId。如果不是這樣,與替換的第一行:

select distinct 

我要指出,有四個層次的樣本數據,而不是三個按問題陳述。

  • A-層:bob
  • B-層:jimtimsam
  • C-層:davkim
  • d層:salvin

即原來的查詢變成:

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,繼=<>者作出的模式。
+0

我認爲你的代碼示例在這裏很好,但我仍然擔心這是一個糟糕的選擇,如何存儲和訪問這些數據。這些查詢不僅不必要地複雜,而且也不會擴展 - 如果添加了第五個級別,該怎麼辦? – ewall 2009-12-24 20:32:34

2

如果您正在使用SQL Server 2008中或者您可以使用SQL Server 2008 - HIERARCHYID數據類型在SQL Server 2008可以非常輕鬆地解決你的問題。檢查下面的這些參考。

Reference 1

Reference 2

下面是如何存儲HierarchyId的全方位分層信息的視覺表示。 alt text http://magmainteractive.net/tutorials/image.axd?picture=WindowsLiveWriter/IntroductiontotheSQLServer2008HIERARCHYI_10473/image_thumb_3.png

+1

+1分享我以前沒見過的東西。涼! – ewall 2009-12-24 20:33:28