2012-02-17 40 views
1

我正在使用SQL Server 2008,我需要匹配部件集。这些部分可以包含其他部分(非递归使其更容易)。SQL Server 2008和子集匹配

表部分

PartId ... 
1 
2 
3 
30 
40 
50 
60 
70 

表PartRelation

PartIdMother PartIdChild (non recursive) 
1   30 
1   40 
1   50 
1   60 

2   30 
2   40 

3   30 
3   40 
3   50 

现在我有一组随机配件的,我想知道哪些聚集部分,这可能是可能的。

表PartRandom

Id  PartId 
1  30 
2  40 
3  70 

显然,部分1,2和3将匹配的线路1和2的查询的预期的结果将是这样的:

预期结果

Id  PartId PartIdMother 
1  30  1 
2  40  1 

1  30  2 
2  40  2 

1  30  3 
2  40  3 

我在这里有一个完全的封锁。请分享您的智慧,以利用SQL 2008的最大。顶级将是TableRelation表中递归关系的支持。

下面是SQL代码:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = 
OBJECT_ID(N'[dbo].[Part]') AND type in (N'U')) 
DROP TABLE [dbo].[Part] 
GO 
CREATE TABLE [dbo].[Part]([PartId] [int] NOT NULL, 
CONSTRAINT [PK_Part] PRIMARY KEY CLUSTERED ([PartId] ASC) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] 
GO 
INSERT INTO [Area51].[dbo].[Part] ([PartId]) VALUES (1) 
INSERT INTO [Area51].[dbo].[Part] ([PartId]) VALUES (2) 
INSERT INTO [Area51].[dbo].[Part] ([PartId]) VALUES (3) 
INSERT INTO [Area51].[dbo].[Part] ([PartId]) VALUES (30) 
INSERT INTO [Area51].[dbo].[Part] ([PartId]) VALUES (40) 
INSERT INTO [Area51].[dbo].[Part] ([PartId]) VALUES (50) 
INSERT INTO [Area51].[dbo].[Part] ([PartId]) VALUES (60) 
INSERT INTO [Area51].[dbo].[Part] ([PartId]) VALUES (70) 
GO 
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = 
OBJECT_ID(N'[dbo].[PartRelation]') AND type in (N'U')) 
DROP TABLE [dbo].[PartRelation] 
GO 
CREATE TABLE [dbo].[PartRelation]([PartIdMother] [int] NOT NULL, 
[PartIdChild] [int] NOT NULL, 
CONSTRAINT [PK_PartRelation] PRIMARY KEY CLUSTERED 
([PartIdMother] ASC, [PartIdChild] ASC) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] 
GO 
INSERT INTO [Area51].[dbo].[PartRelation]([PartIdMother],[PartIdChild]) VALUES(1, 30) 
INSERT INTO [Area51].[dbo].[PartRelation]([PartIdMother],[PartIdChild]) VALUES(1, 40) 
INSERT INTO [Area51].[dbo].[PartRelation]([PartIdMother],[PartIdChild]) VALUES(1, 50) 
INSERT INTO [Area51].[dbo].[PartRelation]([PartIdMother],[PartIdChild]) VALUES(1, 60) 
INSERT INTO [Area51].[dbo].[PartRelation]([PartIdMother],[PartIdChild]) VALUES(2, 30) 
INSERT INTO [Area51].[dbo].[PartRelation]([PartIdMother],[PartIdChild]) VALUES(2, 40) 
INSERT INTO [Area51].[dbo].[PartRelation]([PartIdMother],[PartIdChild]) VALUES(3, 30) 
INSERT INTO [Area51].[dbo].[PartRelation]([PartIdMother],[PartIdChild]) VALUES(3, 40) 
INSERT INTO [Area51].[dbo].[PartRelation]([PartIdMother],[PartIdChild]) VALUES(3, 50) 
GO 
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = 
OBJECT_ID(N'[dbo].[PartRandom]') AND type in (N'U')) 
DROP TABLE [dbo].[PartRandom] 
GO 
CREATE TABLE [dbo].[PartRandom](
[Id] [int] NOT NULL, 
[PartId] [int] NULL, 
CONSTRAINT [PK_PartRandom] PRIMARY KEY CLUSTERED ([Id] ASC) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] 
GO 
INSERT INTO [Area51].[dbo].[PartRandom]([Id],[PartId]) VALUES (1, 30) 
INSERT INTO [Area51].[dbo].[PartRandom]([Id],[PartId]) VALUES (2, 40) 
INSERT INTO [Area51].[dbo].[PartRandom]([Id],[PartId]) VALUES (3, 70) 
+0

由于'70'只出现在'Part'和'PartRandom',我不是什么这是在预料之中的结果参与是明确的。 – 2012-02-17 15:36:44

+0

感谢您的回复。这只是表明PartRandom中的部分实际上是随机的。否则,它可能会误导以为它只包含PartRelation中现有子集的子集。 – Frankenstein 2012-02-17 15:48:40

回答

1

尝试:

select ra.Id, ra.PartId, re.PartIdMother 
from PartRandom ra 
join PartRelation re on ra.PartId = re.PartIdChild 

- 返回其中任何一个子部件都在PartRandom父零件。

编辑:对于一个递归版本,请尝试:

;with cte as 
(select PartIdMother PartIdAncestor, PartIdChild from PartRelation r 
where not exists (select null from PartRelation r1 where r1.PartIdChild = r.PartIdMother) 
/* remove where not exists condition to select all intermediate levels */ 
union all 
select c.PartIdAncestor, r.PartIdChild 
from cte c 
join PartRelation r on c.PartIdChild = r.PartIdMother) 
select ra.Id, ra.PartId, re.PartIdAncestor 
from PartRandom ra 
join cte re on ra.PartId = re.PartIdChild 
+0

谢谢,我认为就是这样。哇,我头上有一个结。你认为递归会同样简单吗? – Frankenstein 2012-02-17 16:12:07

+0

@Frankenstein:查看可​​能的递归查询的更新答案。 – 2012-02-17 17:16:50

+0

这是一个美丽,优雅和简单的解决方案。我真的需要更多地了解SQL Server 2008中的公共表表达式。非常感谢。 – Frankenstein 2012-02-17 17:47:38