2010-05-26 29 views
3

我面臨的問題是,在處理未完全標準化的表格時偶爾會出現問題。這是問題。想象一下有4列的表格,我們稱這個表爲dbo.Hierarchical。下面是表的定義:展平包含引用SQL Server 2005中其他行的行的表格

if OBJECT_ID('dbo.Hierarchical') is not null 
drop table dbo.Hierarchical 

create table dbo.Hierarchical 
(
    colID int not null identity(1,1) primary key 
,GroupName varchar(5) not null 
,IsAtomic bit not null 
,Constituent varchar(5) null 
) 

此表可以具有組名是原子的,這意味着它不沒有部件,或者不能夠原子。在這種情況下,GroupName可以包含其他GroupNames。

爲了清楚起見,讓我們填寫一些數據。

set nocount on 
insert into dbo.Hierarchical values ('A',0,'B') 
insert into dbo.Hierarchical values ('A',0,'C') 
insert into dbo.Hierarchical values ('B',1,'B') 
insert into dbo.Hierarchical values ('C',0,'K') 
insert into dbo.Hierarchical values ('C',0,'L') 
insert into dbo.Hierarchical values ('D',0,'E') 
insert into dbo.Hierarchical values ('D',0,'F') 
insert into dbo.Hierarchical values ('D',0,'G') 
insert into dbo.Hierarchical values ('E',1,'E') 
insert into dbo.Hierarchical values ('F',1,'F') 
insert into dbo.Hierarchical values ('G',0,'H') 
insert into dbo.Hierarchical values ('G',0,'I') 
insert into dbo.Hierarchical values ('H',1,'H') 
insert into dbo.Hierarchical values ('I',1,'I') 
insert into dbo.Hierarchical values ('J',1,'J') 
insert into dbo.Hierarchical values ('K',1,'K') 
insert into dbo.Hierarchical values ('L',1,'L') 
insert into dbo.Hierarchical values ('M',1,'M') 
insert into dbo.Hierarchical values ('N',1,'N') 
set nocount off 

現在,如果我們來看一個簡單的SELECT * FROM dbo.Hierarchical我們得到如下:

GroupName colID  IsAtomic Constituent 
A   1   0   B 
A   2   0   C 
B   3   1   B 
C   4   0   K 
C   5   0   L 
D   6   0   E 
D   7   0   F 
D   8   0   G 
E   9   1   E 
F   10   1   F 
G   11   0   H 
G   12   0   I 
H   13   1   H 
I   14   1   I 
J   15   1   J 
K   16   1   K 
L   17   1   L 
M   18   1   M 
N   19   1   N 

吆,這是長篇大論。現在請注意,前兩行有GroupName A和Constiuents B和C.B是Atomic,所以它沒有更多的便利。但是,C具有便祕K,L(K和L是原子)。我怎樣才能創建一個視圖,將這張表壓平,這樣我只能看到GroupName和Atomic constiuents。在組名A的情況下,我看到768,16 3行

A B 
A K 
A L 
+2

+1對於一個完整的問題和提供DDL和樣本數據。好工作。 – codingbadger 2010-05-26 15:43:51

+0

組成成分是否可以包含自己的成分,或者最多隻有兩個等級? – AakashM 2010-05-26 15:44:19

+0

我不明白輸出,因爲'K'&'L'不會出現在GroupName爲'A'的行中。你是否想要列出每個組名的原子訃告,關於它們是否出現在具有該組名的數據中? – RedFilter 2010-05-26 15:47:01

回答

4

試試這個:

--just a repeat of OP's original table and data 
DECLARE @Hierarchical table 
(colID int not null identity(1,1) primary key 
,GroupName varchar(5) not null 
,IsAtomic bit not null 
,Constituent varchar(5) null) 
set nocount on 
insert into @Hierarchical values ('A',0,'B');insert into @Hierarchical values ('A',0,'C'); 
insert into @Hierarchical values ('B',1,'B');insert into @Hierarchical values ('C',0,'K'); 
insert into @Hierarchical values ('C',0,'L');insert into @Hierarchical values ('D',0,'E'); 
insert into @Hierarchical values ('D',0,'F');insert into @Hierarchical values ('D',0,'G'); 
insert into @Hierarchical values ('E',1,'E');insert into @Hierarchical values ('F',1,'F'); 
insert into @Hierarchical values ('G',0,'H');insert into @Hierarchical values ('G',0,'I'); 
insert into @Hierarchical values ('H',1,'H');insert into @Hierarchical values ('I',1,'I'); 
insert into @Hierarchical values ('J',1,'J');insert into @Hierarchical values ('K',1,'K'); 
insert into @Hierarchical values ('L',1,'L');insert into @Hierarchical values ('M',1,'M'); 
insert into @Hierarchical values ('N',1,'N');set nocount off 

--declare and set starting position 
DECLARE @Start varchar(5) 
SET @Start='A' 

--get the data 
;WITH HierarchicalTree AS 
(
    SELECT 
     GroupName, Constituent, 1 AS LevelOf 
     FROM @Hierarchical 
     WHERE [email protected] 
    UNION ALL 
     SELECT 
      t.GroupName, h.Constituent, t.LevelOf+1 
     FROM HierarchicalTree   t 
      INNER JOIN @Hierarchical h ON t.Constituent=h.GroupName 
     WHERE h.Constituent!=h.GroupName AND h.IsAtomic=0 
) 
SELECT 
    t.GroupName,t.Constituent 
    FROM HierarchicalTree  t 
     INNER JOIN @Hierarchical h ON t.Constituent=h.GroupName 
    WHERE h.IsAtomic=1 

OUTPUT:

GroupName Constituent 
--------- ----------- 
A   B 
A   K 
A   L 

(3 row(s) affected) 
+0

這就是答案!這工作完美。我現在正在通過遞歸邏輯來查看我是否理解它,但是它產生了正確的表格!非常感謝。 – gr928x 2010-05-26 20:35:08

0

嗯,這的確你問什麼,但如果它嵌套一旦它只會工作。如果你需要遞歸,那麼你將不得不使用CTE。

select a.GroupName, 
     b.Constituent 

From dbo.Hierarchical a 

Left Join dbo.Hierarchical b on a.Constituent = b.GroupName 

這是你所需要的還是我完全錯過了這一點?

+0

這幾乎是正確的,但問題是這隻能處理2層嵌套。因此,如果我通過將 插入到dbo中來製作L非原子。分層值('L',0,'M') insert into dbo.Hierarchical values('L',0,'N') 此查詢不會給我預期結果 A - > B A - > K A - > M A - > N 我想我需要一些能夠遞歸地處理表中所有嵌套層次的東西,而不必事先知道表格中嵌套的深度。 – gr928x 2010-05-26 16:14:40

+0

是的,您需要使用公共表格表達式(CTE)。 http://www.4guysfromrolla.com/webtech/071906-1.shtml – codingbadger 2010-05-26 16:23:11

+0

是的,我想CTE是要走的路,但我不知道如何編寫CTE,以便抓取嵌套關卡並給出我是GroupName和Atomic Consituents。如果我知道我會發布它。 – gr928x 2010-05-26 16:55:02

0

爲了完整起見,我隨信附上了設置了問題,並給出瞭解決方案整個SQL腳本文件。再次,Hattip KM。

use tempdb 
go 

if OBJECT_ID('dbo.Hierarchical') is not null 
    drop table dbo.Hierarchical 

create table dbo.Hierarchical 
(
    colID   int   not null identity(1,1) primary key 
    ,GroupName  varchar(5) not null 
    ,IsAtomic  bit   not null 
    ,Constituent varchar(5) null 
) 

set nocount on 
insert into dbo.Hierarchical values ('A',0,'B') 
insert into dbo.Hierarchical values ('A',0,'C') 
insert into dbo.Hierarchical values ('B',1,'B') 
insert into dbo.Hierarchical values ('C',0,'K') 
insert into dbo.Hierarchical values ('C',0,'L') 
insert into dbo.Hierarchical values ('D',0,'E') 
insert into dbo.Hierarchical values ('D',0,'F') 
insert into dbo.Hierarchical values ('D',0,'G') 
insert into dbo.Hierarchical values ('E',1,'E') 
insert into dbo.Hierarchical values ('F',1,'F') 
insert into dbo.Hierarchical values ('G',0,'H') 
insert into dbo.Hierarchical values ('G',0,'I') 
insert into dbo.Hierarchical values ('H',1,'H') 
insert into dbo.Hierarchical values ('I',1,'I') 
insert into dbo.Hierarchical values ('J',1,'J') 
insert into dbo.Hierarchical values ('K',1,'K') 
insert into dbo.Hierarchical values ('L',1,'L') 
insert into dbo.Hierarchical values ('M',1,'M') 
insert into dbo.Hierarchical values ('N',1,'N') 
set nocount off 

-- see what the over nomalized table looks like 
-- before you call the CTE. Notice how A has 
-- Constiuents B, and C. And further down 
-- C is made up of K, and L. 

-- select * from dbo.Hierarchical 

go 


-- Use the CTE to 
;WITH HierarchicalTree AS 
( 
    SELECT 
     GroupName, Constituent, 1 AS LevelOf 
     FROM dbo.Hierarchical 
     --WHERE [email protected] 
    UNION ALL 
     SELECT 
      t.GroupName, h.Constituent, t.LevelOf+1 
     FROM HierarchicalTree   t 
      INNER JOIN dbo.Hierarchical h ON t.Constituent=h.GroupName 
     WHERE h.Constituent!=h.GroupName AND h.IsAtomic=0 
) 


-- Now, notice this query will give us A with the it's 
-- Constiuent elements B, K, and L 
SELECT 
    t.GroupName,t.Constituent, h.IsAtomic, t.LevelOf 
    FROM HierarchicalTree  t 
     INNER JOIN dbo.Hierarchical h ON t.Constituent=h.GroupName 
    --WHERE h.IsAtomic=1 
    Where h.Constituent = h.GroupName 
order by 
    t.GroupName 

if OBJECT_ID('tempdb..Hierarchical') is not null 
    drop table dbo.Hierarchical 
相關問題