我正在制作一个我有食谱的系统。 RecipeItem是完成该配方将产生的。 CraftMaterials是必须组合才能完成配方的组件。
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 :(得分: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