展平包含引用SQL Server 2005中其他行的行的表

时间:2010-05-26 15:33:15

标签: sql sql-server sql-server-2005 views

我遇到的问题是,当您处理未完全规范化的表时,偶尔会出现问题。这是问题所在。想象一下有4列的表,让我们把这个表称为dbo.Hierarchical。以下是该表的定义:

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
)

此表可以具有Atomic的GroupName,这意味着它没有组件,或者不能是Atomic。在这种情况下,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

现在,如果我们从dbo.Hierarchical看一个简单的select *,我们得到以下内容:

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,所以它没有其他的constiuents。然而,C具有钾,L(K和L是原子)。如何创建一个将该表展平的视图,以便我只看到GroupName和Atomic constiuents。在GroupName A的情况下,我应该看到3行

A B
A K
A L

3 个答案:

答案 0 :(得分: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 GroupName=@Start
    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

输出:

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

(3 row(s) affected)

答案 1 :(得分:0)

这就是你所要求的,但只有嵌套一次才会有效。如果你需要递归,那么你将不得不使用CTE。

select a.GroupName,
        b.Constituent

From dbo.Hierarchical a

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

这是你需要的还是我完全错过了这一点?

答案 2 :(得分: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 GroupName=@Start 
    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