2012-05-08 48 views
3

我有一個數據表,其中包含技術上是樹結構的數據,但樹是由代碼和此代碼的長度定義的。基於SQL中的代碼計算樹級別

的商品代碼表包括的代碼和描述:

例如:

Code Description 
------ ------------- 
0101 Live Animals 
01011 Horses 
010110 Purebred 
010190 Other 

項目的級別是由在其下方計數碼計算。它下面的代碼必須包含在當前代碼中。如果那有意義的話。

所以在上面的例子:

0101 is level 0 (nothing is contained in it) 
01011 is level 1 (0101 is contained in it) 
010110 is level 2 (0101 and 01011 is contained in it) 
010190 is level 1 (only 0101 is contained in it) 

有沒有辦法讓SQL這些水平?我正在使用DB2。

編輯: 尼古拉和戈登的解決方案都工作得很好,雖然我認爲尼古拉的速度稍快!感謝你們!

不得不做出一些修改,以考慮DB2:

select 
    t1.code, count(t2.code) 
from commoditycode t1 
left join commoditycode t2 
on substr(t1.code, 1, length(t1.code) - 1) like concat(t2.code, '%') 
group by t1.code 
+1

哪個DBMS? PostgreSQL的?甲骨文? DB2? –

+0

你可以調整數據的存儲方式麼?這不是一個選項嗎? – Purplegoldfish

+0

不幸的是我無法重組數據。我目前正在通過計算Java中的級別來解決這個問題。這是相當快速和高效的,但想知道是否有可能在純SQL中執行此操作。 – Neil

回答

4

聯接到本身代碼減去最後一個字符會發現所有的父母在右側。計數他們將得到的項目級別:

declare @test table (code varchar(10), name varchar(100)) 

insert into @test values ('0101', 'Live Animals') 
insert into @test values ('01011', 'Horses') 
insert into @test values ('010110', 'Purebred') 
insert into @test values ('010190', 'Other') 

select t1.code, t1.name, count (t2.code) + 1 [level] 
    from @test t1 
    left join @test t2 
    on substring (t1.code, 1, len (t1.code) - 1) like t2.code + '%' 
group by t1.code, t1.name 


code name   level 
01011 Horses   2 
0101 Live Animals 1 
010190 Other   2 
010110 Purebred  3 
+0

謝謝!非常聰明的解決方案,它運作良好。 刪除了+1,因爲0101是第0級。 – Neil

4

有趣的問題。如果我理解正確,這可以使用標準SQL解決。

這是想法。對於每個代碼,我想將其與所有其他代碼進行比較。我只關心其他代碼,其中第一個代碼的開頭與整個其他代碼相匹配。

一旦我有這個,我算了算這樣的碼數:

select code, description, count(*) as level 
from 
(
    select c.code, c.description, c2.code as abovecode 
    from commmodity c 
    left outer join commodity c2 on 
    on left(c.code, len(c2.code)) = c2.code 
    and c.code <> c2.code 
    group by c.code, c2.code 
) c 
group by code, description