唯一集的数据模型

时间:2015-02-12 14:27:42

标签: sql-server data-modeling

我正在寻找实施数据模型的最佳方式"食谱"

像披萨应用程序一样思考,你可以自己制作披萨。您可以选择100种成分中的5种,然后为每种成分选择一种量。我需要检查一下我是否已经看过"之前的披萨组合,如果我没有,则分配ID,如果我有,则检索ID。

我们有 n 成分。

配方由一组成分和相应的量定义。

看起来像:

Ingr1 90
Ingr2 10


Ingr1 90
Ingr2 10
Ingr3 10

我想将这个存储在一个结构中,我给每个唯一的食谱一个ID,所以我可以在给定食谱数据集的情况下查询ID。

我想要一个存储过程,它将数据集作为参数,并返回一个ID,如果配方未知则返回新ID,如果配方已经存在则返回。

我正在寻找最有效的方法。到目前为止,我最好的想法是将配方编码为字符串(json)并将其用作唯一约束,或者使用存储过程迭代配方数据集并构造n级深度if exists语句。

所以,我有信心我可以解决问题,但我正在寻找一种漂亮的方法。

1 个答案:

答案 0 :(得分:1)

据我所知,你有实体配方和成分以及它们之间的M:M关系。数据模型看起来像这样(粗体PK):

配方( RecipeID ,RecipeName)

成分( IngredientID ,IngredientName)

RecipeIngredients( RecipeID IngredientID ,金额)

您可以使用查询解决查找数据库中是否已存在相同配方的任务,但此查询并不简单。这是众所周知的问题,关系分工。有几种方法。其中最受欢迎的是数量。如果某些食谱的成分与目标成分相同,并且所有成分都相同,则它们是相同的。此类查询通常涉及数据聚合,并且对大量数据的执行速度不是很快。

您可以从应用程序方面帮助解决此问题,并且您正在考虑正确的方向。将配方表示为字符串,按成分ID排序值(即使成分按不同顺序添加也能获得相同的字符串),以某种稳定的形式转换金额(不是获得0.499999而不是0.5),计算字符串中的一些散列,并存储食谱中的这个值。简单形式hash是一个整数值,因此你可以非常快地找到双精度。

所以这是你的电话。每种方法都有它自己的问题。在第一种情况下进行大量查询并且在第二种情况下将哈希保持在实际状态(以及可能的冲突)也很麻烦。我坚持使用第一个选项,直到它正常工作,并且只有当它们不可避免时才开始任何优化。

查询示例(新配方位于#tmp中):

;with totals as
(
  select RecipeID, count(*) totals
  from RecipeIngredients
  group by RecipeID
), matched_totals as
(
  select i.RecipeID, count(*) matched_totals
  from RecipeIngredients i
    join #tmp t
      on i.IngredientID = t.IngredientID
        and i.Amount = t.Amount
  group by i.RecipeID
)
select t.*
from totals t
  join matched_totals m
    on m.RecipeID = t.RecipeID
where
  totals = matched_totals
  and totals = (select count(*) from #tmp)

此解决方案更优雅,但更不直观:

select * 
from Recipe r
where
  not exists 
    ( select 1 
      from RecipeIngredients ri
      where 
        r.RecipeID = ri.RecipeID
        and not exists
        (select 1 from #tmp t where t.IngredientID = ri.IngredientID)
    )    
相关问题