2014-10-11 182 views
1

我正在使用一个系统,我有一个食谱。 RecipeItem是完成该配方的成果。工艺材料是必须组合才能完成配方的组件。CTE递归查询

CREATE TABLE Recipe 
(
    RecipeId bigint 
    ...other data 
) 

CREATE TABLE CraftMaterial 
(
    CraftMaterialId bigint, 
    ItemId    bigint, 
    RecipeId   bigint, 
    Amount    int 
) 

CREATE TABLE RecipeItem 
(
    RecipeItemId  bigint 
    RecipeId   bigint, 
    ItemId   bigint, 
    Amount   int 
) 

CREATE TABLE Item 
(
    ItemId  bigint 
    Name  varchar(200) 
    IconName varchar(200) 
) 

当你做对加盟配方 - > RecipeItem - >项目,你得到的配方,使该项目的兴田名。食谱项目存储了该项目的创建数量。

当您加入配方 - > CraftMaterial - >项目时,您将获得组合在一起的项目列表。

配方的材料可能本身就是一个配方。

我正在做的是使用CTE来获取每个构造级别的材质,直到我到达基础物品 - 即CraftMaterial中的物品在RecipeItem中没有相应的记录。

我到目前为止正确地获得了物品的第一层配方。这是查询的递归部分给我带来麻烦。

DECLARE @RecipeId int 

SET @RecipeId = 5951 

;WITH cteMaterials (CCraftMatId, ItId, RecId, Amt, Name, Icon, MatLevel) 
AS 
(
    SELECT 
     cm.CraftMaterialId, 
     cm.ItemId, 
     cm.RecipeId, 
     cm.Amount, 
     i.Name, 
     i.IconFileName, 
     1 
    FROM CraftMaterial cm 
    JOIN Item i ON cm.ItemId = i.ItemId 
    WHERE cm.RecipeId = @RecipeId 

    UNION ALL 

    ??? 
) 

select * from cteMaterials 
+0

为什么不持有方的名字?你从项目表中获得什么? – 2014-10-11 01:51:58

+0

你能提供一些样本数据吗? – SouravA 2014-10-11 03:54:46

回答

1

尼斯的挑战,有一点与关系的斗争中,他们不觉得很自然与工作,但我可以看到他们是如何使用的。查找工作下面的例子或尝试here

数据设置

if (object_id('Recipe') is not null) 
    drop table Recipe 
if (object_id('RecipeItem') is not null) 
    drop table RecipeItem 
if (object_id('CraftMaterial') is not null) 
    drop table CraftMaterial 
if (object_id('Item') is not null) 
    drop table Item 

create table Recipe (RecipeId bigint) 

create table CraftMaterial 
(
    CraftMaterialId bigint identity(1, 1), 
    ItemId bigint, 
    RecipeId bigint, 
    Amount int 
) 

create table RecipeItem 
(
    RecipeItemId bigint identity(1, 1), 
    RecipeId bigint, 
    ItemId bigint, 
    Amount int 
) 

create table Item 
(
    ItemId bigint identity(1, 1), 
    Name varchar(200), 
    IconName varchar(200) 
) 

declare @id bigint = 0 

insert Recipe 
     (RecipeId) 
values 
     (5951), 
     (5952), 
     (5953), 
     (5954) 

insert Item 
     (Name, IconName) 
values 
     ('Chocolate Cupcakes', 'cc_ico') 
select 
    @id = @@IDENTITY 

insert RecipeItem 
     (RecipeId, ItemId, Amount) 
values 
     (5951, @id, 12) 

insert Item 
     (Name, IconName) 
values 
     ('Flour', 'flour_ico') 
select 
    @id = @@IDENTITY 

insert CraftMaterial 
     (ItemId, RecipeId, Amount) 
values 
     (@id, 5951, 1) 

insert Item 
     (Name, IconName) 
values 
     ('chocolate', 'choc_ico') 
select 
    @id = @@IDENTITY 

insert RecipeItem 
     (RecipeId, ItemId, Amount) 
values 
     (5952, @id, 2) 

insert CraftMaterial 
     (ItemId, RecipeId, Amount) 
values 
     (@id, 5951, 1) 

insert Item 
     (Name, IconName) 
values 
     ('milk', 'milk_ico') 
select 
    @id = @@IDENTITY 

insert CraftMaterial 
     (ItemId, RecipeId, Amount) 
values 
     (@id, 5952, 300) 

insert RecipeItem 
     (RecipeId, ItemId, Amount) 
values 
     (5953, @id, 1) 

insert Item 
     (Name, IconName) 
values 
     ('cocao', 'cocao_ico') 
select 
    @id = @@IDENTITY 

insert CraftMaterial 
     (ItemId, RecipeId, Amount) 
values 
     (@id, 5952, 75) 

insert RecipeItem 
     (RecipeId, ItemId, Amount) 
values 
     (5954, @id, 1) 

insert Item 
     (Name, IconName) 
values 
     ('cow', 'cow_ico') 
select 
    @id = @@IDENTITY 


insert CraftMaterial 
     (ItemId, RecipeId, Amount) 
values 
     (@id, 5953, 1) 

insert Item 
     (Name, IconName) 
values 
     ('cocao bean', 'cbean_ico') 
select 
    @id = @@IDENTITY 

insert CraftMaterial 
     (ItemId, RecipeId, Amount) 
values 
     (@id, 5954, 250) 

CTE例

declare @RecipeId int 

set @RecipeId = 5951; 

with cteMaterials(CCraftMatId, ItId, RecId, Amt, Name, Icon, ChildItem, MatLevel) 
      as (
       select 
        cm.CraftMaterialId, 
        cm.ItemId, 
        cm.RecipeId, 
        cm.Amount, 
        i.Name, 
        i.IconName, 
        cm.ItemId ChildItem, 
        1 MatLevel 
       from 
        RecipeItem as ri 
        inner join CraftMaterial as cm 
         on cm.RecipeId = ri.RecipeId 
        inner join Item as i 
         on cm.ItemId = i.ItemId 
       where 
        ri.RecipeId = @RecipeId 
       union all 
       select 
        cm.CraftMaterialId, 
        cm.ItemId, 
        cm.RecipeId, 
        cm.Amount, 
        i.Name, 
        i.IconName, 
        cm.ItemId ChildItem, 
        cteMaterials.MatLevel + 1 
       from 
        RecipeItem as ri 
        inner join CraftMaterial as cm 
         on cm.RecipeId = ri.RecipeId 
        inner join Item as i 
         on cm.ItemId = i.ItemId 
        inner join cteMaterials 
         on cteMaterials.ChildItem = ri.ItemId 
       ) 
    select 
     cteMaterials.CCraftMatId, 
     cteMaterials.ItId, 
     cteMaterials.RecId, 
     cteMaterials.Amt, 
     cteMaterials.Name, 
     cteMaterials.Icon, 
     cteMaterials.MatLevel 
    from 
     cteMaterials