2014-10-11 3 views
1

Я работаю над системой, где у меня есть рецепт. РецептItem - это то, что завершает этот рецепт. CraftMaterials - это компоненты, которые необходимо комбинировать для завершения рецепта.Рекурсивный запрос 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 -> Item, вы получаете Hte имя элемента рецепт делает. В элементе рецепта хранится, сколько из этого элемента создано.

Когда вы присоединяетесь к рецепту -> CraftMaterial -> Item, вы получаете список предметов, которые объединены, чтобы сделать этот рецепт.

Материал (и) рецепта может быть самим рецептом.

Что я хочу сделать, это использовать 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

почему не Recipe держать имя? что вы получаете из таблицы предметов? –

+0

Можете ли вы предоставить некоторые данные образца? – SouravA

ответ

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) 

КТР Пример

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 
Смежные вопросы