数据库设计模型,用于无限共享和唯一项目分类

时间:2012-01-20 21:45:46

标签: database-design classification

基本上,我想创建一个数据库结构,允许以无限的方式对无限量的库存项目进行分类,但是,其中许多项目共享某些“traits”。例如,CarsTrucks

  • 两者都只能是redblue
    • 彩色汽车/卡车可以是2wd4wd
      • Cars可以manualautomatic传输。
      • Trucks可以有clothleather个席位
      • 等...

我希望避免的是手动输入存在的每种可能的组合。有5种颜色和5种车辆,已经有25个条目,没有功能集分类。

是否存在允许这些关系和共享“特征组”的数据模型,或者更重要的是,是否允许对我可以想象的任何数据集的每种可能组合进行单一引用?任何帮助将不胜感激。

更新[2012-01-23]

让我尽可能具体。我的主要目标是跟踪材料使用情况 我们为预算和历史目的而做的工作。一些材料, 即 studs track ,将共享相同的子分类, 跟踪还有第3个子分类。有些人会完全 不同的分类。假设如下。

  • 5可能metal_widths
  • 5可能metal_gagues
  • 4可能track_types
  • 5可能insulation_widths
  • 3可能insulation_types

......关系(可能的组合):

  • Studs> metal_widths> metal_gagues 25
  • Track> metal_widths> metal_gagues> track_types 100
  • Insulation> insulation_widths> insulation_types 15

为了了解我的最终目标,应用程序工作流程将是 像这样的东西:

  1. 创造一份工作。
  2. 创建工作预算。
    • 为我希望使用的每种材料设置预算金额/成本。
  3. 开始输入物料发票。
    • 为发票上的每种材料设置金额/成本。
  4. 跟踪/审核我的预算估算值与实际费用。
  5. 我认为我的预算与费用应用程序的目标非常简单, 我只是想让之前的材料相关数据库的设计正确 向前进。我意识到最简单的解决方案是创建单个 material表中每个可能组合的条目并限制它 数据库到n个可能的特征。问题是,当我决定 添加x width个帖子,我还想添加x width曲目,意思是我 将可能的组合增加30 ,因此需要30 额外的条目(我真的宁愿避免)。

    我的问题仍然相同:是否有允许这些的数据模型 关系,更重要的是,有一个允许单一参考 对于每种可能性...... ,我应该抓住这个概念并继续使用 每种材料的单个条目,并限制特征的数量。

7 个答案:

答案 0 :(得分:5)

你的意思是这样的吗?

enter image description here

这个简单的模型允许您将特征组合在一起然后将整个特征组“应用”到任意数量的项目(ITEM_TRAIT_GROUP表格是M:N关系的典型示例可以用关系范式表示)。如果您主要关心的是避免通过“重复使用”特征来重复,那么这个模型可能适合该法案。

然而,这将强制执行:

  1. 特定物品种类的任何特定特征组(例如需要颜色的汽车)或特征之间的任何特定关系(例如座椅材料必须与座椅颜色一起),
  2. 也不会限制任何特定特征的值(例如颜色必须是“红色”或“蓝色”但不是,例如“绿色”)。
  3. (1)和(2)会要求某种类型的系统甚至是“继承”(在OOP意义上),这在关系范式中并不乐趣。如果你真的需要它,你最好在客户端或中间层强制执行这种逻辑。

    (3)可以合理地建模,但并非没有使模型复杂化,这可能是也可能不值得付出努力。

答案 1 :(得分:1)

我不确定我理解你的意思“因此需要30个额外的条目”。除非实际携带信息,否则您不必明确输入所有组合。例如,如果您有一个包含所有价格的供应商价格表,那么您将有30个额外的行,每个行都有一个新价格。但这似乎不是你想要的。您似乎想要为构成工作的所有项目的预算和后期发票价格输入。

让我们尝试以直截了当的方式解决问题:

METAL_WIDTH
id | unit | amount | displaytext
 1 |  mm  |   10   |  2/5 in
 2 |  mm  |   15   |  3/5 in
 3 |  mm  |   20   |  4/5 in
 4 |  mm  |   25   |  1 in
 5 |  mm  |   30   |  1 1/5 in

METAL_GAUGE...
TRACK_TYPE...
INSULATION_WIDTH...
INSULATION_TYPE...

我跳过了其他四个表的细节,它们的结构类似于METAL_WIDTH

JOB
id | name
 1 | test job


BUDGET_ITEM
id | job_id | type | metal_width_id | metal_gauge_id | track_type_id | insulation_width_id | insulation_type_id | price_in_dollar
1  |    1   | STUD |       1        |      1         |    null       |      null           |     null           |    50

INVOICE_ITEM
id | job_id | type | metal_width_id | metal_gauge_id | track_type_id | insulation_width_id | insulation_type_id | price_in_dollar
1  |    1   | STUD |       1        |      1         |    null       |      null           |     null           |    49.95

这里我将INVOICE_ITEM和BUDGET_ITEM分开,因为我觉得你可能想要使用INVOICE_ITEM而不仅仅是预算控制。但是你可以把所有项目都放到一个大的JOB_ITEMS表中。相反的情况也是可能的:您可以创建一个STUD_PRICE表,一个TRACK_PRICE和一个INSULATION_PRICE。更多表意味着查询变得更长,但现在您可以存储STUD只能具有METAL_GAUGE和METAL_WIDTH属性的信息:

STUD_PRICE
id | job_id | purpose | metal_width_id | metal_gauge_id | price
 1 |    1   | BUDGET  |       1        |       1        |  50
 2 |    1   | INVOICE |       1        |       1        |  49.95

现在您可能会注意到您有一个冗余:两次输入相同的螺柱,如果您想比较预算和发票,并且在工作中有多个螺柱,这将成为一个问题:< / p>

STUD_PRICE
id | job_id | purpose | metal_width_id | metal_gauge_id | price
 1 |    1   | BUDGET  |       1        |       1        |  50
 2 |    1   | INVOICE |       1        |       1        |  49.95
 3 |    1   | BUDGET  |       1        |       2        |  75
 4 |    1   | INVOICE |       1        |       2        |  89.95

INVOICE现在属于哪个BUDGET?你是一个有趣问题的错字。所以你可能会更好:

STUD_ITEM
id | job_id | metal_width_id | metal_gauge_id | budget_price | invoice_price
 1 |    1   |       1        |       1        |  50          |   49.95
 2 |    1   |       1        |       2        |  75          |   null

其中null表示“尚未开票”,一旦您在那里,您可以从上面获取BUGET_ITEM和INVOICE_ITEM表并将它们组合到JOB_ITEM

JOB_ITEM
id | job_id | type | metal_width_id | metal_gauge_id | track_type_id | insulation_width_id | insulation_type_id | budget_price | invoice_price
1  |    1   | STUD |       1        |      1         |    null       |      null           |     null           |    50        | 49.95

您的应用程序将允许您创建新作业,设置其属性,然后将项目添加到其预算中。您可以说“新项目......”并可在STUD,TRACK和INSULATION之间进行选择。选择STUD后,您将获得一个包含允许的METAL_WIDTH的菜单,另一个包含允许的METAL_GAUGE。您可以选择它们,设置预算价格并存储该项目。根据需要重复。进入发票阶段后,选择存储的项目并设置发票价格。预算/发票比较是通过查看作业中的所有项目,添加预计总预算的所有预算价格,并添加实际总发票金额的所有发票,还有奖励积分,也仅显示那些项目的预算成本invoice_price不为空。

要为发票创建文本,您只需连接displaytext列的内容,从而节省每个“Stud - 2/5 in - 10ga”到“Stud - 1 1/5”的行的需要在 - 18ga“。如果你现在添加一个METAL_WIDTH,你所要做的就是在METAL_WIDTH表中添加一行,你很好。

答案 2 :(得分:0)

上汽车课。汽车可以是卡车,也可以是汽车。也许你应该研究继承和抽象 - 面向对象设计的两个基础。

答案 3 :(得分:0)

我不确定“每种可能性的单一参考点”是什么意思。

可以简单地将数据输入到一个宽的varchar()列中,如

  • 螺柱,8 mm,8 ga
  • 螺柱,10 mm,8 ga
  • 螺柱,12 mm,6 ga
  • 轨道,8毫米,8千克1型
  • 轨道,10 mm,8 ga 2型

这不要求您提前输入任何内容,并且它提供了最大的灵活性,尽管这种灵活性是以数据完整性为代价的。 (或者通过不断观察错误条目来增加管理开销。)它也会使报告复杂化。例如,仅报告8个量规螺柱更复杂。

现成的会计系统 - 已经过编程处理预算,估算和发票 - 通常会要求您以这种方式存储库存。

假设您已经做出有意识的,明智的决定不使用您的会计系统,那么您根本不会以这种方式存储值,而是希望外键约束带来更大的数据完整性,自动生成集合可能是有意义的。

-- This table will be used as a foreign key reference for tracks. 
-- Adjust the CHECK() constraints for your actual values. If you're using MySQL,
-- replace the CHECK() constraints with foreign key references to separate tables.
--
create table studs (
  metal_width_mm integer not null check (metal_width_mm between 5 and 10),
  metal_gauge integer not null check (metal_gauge between 8 and 16),
  primary key (metal_width, metal_gauge)
);

要填充它,将已知值放入公用表表达式,并生成笛卡尔积。

insert into studs
with gauge as (
  select 8 as metal_gauge
  union all
  select 10
  union all
  select 12
  union all
  select 14
  union all
  select 16
),
width as (
  select 5 as metal_width_mm
  union all
  select 6
  union all
  select 7
  union all
  select 8
  union all
  select 9
  union all
  select 10
)
select * 
from width, gauge

如果必须经常添加值,则编写SQL存储过程以仅插入新组合并不困难。

如果您没有寻求这么大的灵活性或这么多的数据完整性,请考虑澄清您的问题。

答案 4 :(得分:0)

当我在Onan工作并且他们必须跟踪发电机组的有效配置时,他们使用了两个表,并且必须使用&#39;并且不允许。&#39;

所以,举个例子:

cars and trucks,
    Both can be red or blue only.
    Either color car/truck can be 2wd or 4wd.
        Cars can have manual or automatic transmission.
        Trucks can have cloth or leather seats

必须使用&#39;表,会有像

这样的规则

<强> object | attribute | mustUse1 | orMustUse2

car | color | red | blue
truck | color | red | blue
car | wd | 2wd | 4wd
truck | wd | 2wd | 4wd
car | transmission | manual | automatic
truck | seats | cloth | leather

在您的情况下,如果您有很多重复项,您可能会存储更高级别的关系,例如carstrucks autos,然后在&#中39;必须使用&#39;表,只是

auto | color | red | blue
auto | wd | 2wd | 4wd
car | transmission | manual | automatic
truck | seats | cloth | leather

另外,我不确定为什么可能的组合会让你感到困惑。 给定

    5 possible metal_widths
    5 possible metal_gagues
    4 possible track_types
    5 possible insulation_widths
    3 possible insulation_types

...the relationships (possible combinations):

    Studs > metal_widths > metal_gagues (25)
    Track > metal_widths > metal_gagues > track_types (100)
    Insulation > insulation_widths > insulation_types (15)

metal_widths提供5行,metal_gauges包含5行,studs包含metal_widthID和metal_gaugeID,track包含(studID?)和track_typeID,和insulation,其中包含insulation_widthID和insulation_typeID。

如果您觉得自己的体验不足以建模并应用数据,那么您可以让其他人这样做。

答案 5 :(得分:0)

是RDBMS的要求吗?您可以使用graphDB代替Neo4j吗?

答案 6 :(得分:0)

我通过将项目(和引号)建模为具有类型的对象并使用键值对指定特征来接近它。以示例的方式显示表格,并忽略主键之类的内容:

首先有一个包含所有有效键值对的表:

VALID_KEY_VALUES
| key             | value   |
=============================
| metal_width     | mwidth1 |
| metal_width     | mwidth2 |
...
| insulation_type | itype3  |

这可满足您的要求,如果您需要添加新的metal_width,则可以在此表中插入一个。{p> (目前示例中有22行)。

现在有一个每种类型的有效密钥表:

VALID_TYPE_KEYS
| type       | key              |
=================================
| stud       | metal_width      |
| stud       | metal_gauge      |
| track      | metal_width      |
| track      | metal_gauge      |
| track      | track_type       |
| insulation | insulation_width |
| insulation | insulation_type  |

现在,一个项目(或引用)由两个表定义,首先是ID:

的项目
ITEMS
| ID | type | .... whatever columns you need ...
================================================
| 1  | stud | ..................................

现在&#34;特征&#34;该项目:

ITEM_TRAITS
| itemID | type | key         | value   |
=========================================
| 1      | stud | metal_width | mwidth1 |
| 1      | stud | metal_gauge | mgauge2 |

(这有点非规范化,因为每行包含来自itemID表的typeITEMS,但我们暂时可以使用它。换句话说,第1项是具有metal_width=mwidth1, metal_gauge=mgauge2的螺柱。

您可以使用ITEM_TRAITS表中的多列外键将它们粘在一起。

(itemID, type) is a foreign key into the ITEMS table
(type, key) is a foreign key to the VALID_TYPE_KEYS table
(key, value) is a foreign key to the VALID_KEY_VALUES table

这似乎是您需要的良好开端。如果您需要添加新类型,新特征或特征的新值,则使用最小插入完成。您的报价可以使用QUOTESQUOTE_TRAITS表格以类似方式完成。您可以通过连接匹配带引号的项目,计算项目和引用之间匹配的特征数量(并将其与给定类型的特征总数进行比较)。

您可能需要在客户端上做一些工作,迭代给定类型的所有键,以确保输入所有必要的数据,并且这确实假设您的每一个&#34;组合&#34;已验证。 (如果你的情况下某些组合是有效的而有些组合不是,那么你将无法避免全部枚举它们)。这也假设没有&#34;下钻&#34;也就是说,指定一个特征的逻辑并不限制任何后期特征的值,但你甚至可以将这个想法扩展到这种情况(假设你的要求也不是疯了)。