2014-10-11 174 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