78

这是一个与“编程”无关的问题(不是特定于任何语言或数据库),而是更多的设计和体系结构。这也是“什么是做 X 的最佳方式”类型的问题。我希望不会引起太多“宗教”争议。

在过去,我开发了一种系统,以一种或另一种方式保留某种形式的项目库存(与哪些项目无关)。一些使用不支持事务的语言/数据库。在这些情况下,我选择不在项目记录的字段中保存手头的项目数量。相反,现有数量是计算收到的总库存 - 已售库存的总和。由于软件,这导致库存几乎没有差异。这些表已正确索引并且性能良好。如果记录量开始影响性能,则会有一个归档过程。

现在,几年前我开始在这家公司工作,我继承了一个跟踪库存的系统。但是数量保存在一个字段中。注册条目后,收到的数量将添加到项目的数量字段中。当一件商品售出时,数量会被减去。这导致了分歧。在我看来,这不是正确的方法,但这里以前的程序员发誓。

我想知道对于设计这样的系统的正确方法是否有共识。还有什么可用的资源,印刷的或在线的,以寻求这方面的指导。

谢谢

4

12 回答 12

56

我在我现在的公司看到了这两种方法,并且肯定会倾向于第一种(根据股票交易计算总数)。

如果您只在某个字段中存储总数量,您将不知道您是如何得出该数字的。没有交易历史记录,您最终可能会遇到问题。

我编写的最后一个系统通过将每笔交易存储为具有正数或负数的记录来跟踪库存。我发现它工作得很好。

于 2008-11-13T14:47:24.917 回答
9

视情况而定,库存系统不仅仅是对物品进行计数。例如,出于会计目的,您可能需要了解基于 FIFO(先进先出)模型的库存会计价值。这不能通过简单的“收到的总库存 - 售出的总库存”公式来计算。但是他们的模型可能会很容易地计算出这一点,因为他们会随时修改会计价值。我不想详细说明,因为这不是编程问题,但如果他们发誓,也许你没有完全理解他们必须满足的所有要求。

于 2008-11-13T14:50:07.423 回答
7

两者都是有效的,视情况而定。当以下条件成立时,前者是最好的:

  • 要求和的项目数相对较少
  • 很少或没有特殊情况需要考虑(退货、调整等)
  • 库存项目数量不是经常需要

另一方面,如果你有大量的物品,有几个例外情况,并且经常访问,那么保持物品数量会更有效率

另请注意,如果您的系统存在差异,则它存在应追踪和消除的错误

我已经完成了两种方式的系统,两种方式都可以正常工作 - 只要你不忽略错误!

于 2008-11-13T15:29:30.213 回答
4

重要的是要考虑现有系统以及更改它的成本和风险。我使用的数据库存储类似于您的库存,但它包括审计周期和存储调整,就像收据一样。它似乎运作良好,但所涉及的每个人都训练有素,而且仓库工作人员学习新程序的速度并不快。

在您的情况下,如果您正在寻找更多跟踪而不更改整个数据库结构,那么我建议添加一个跟踪表(类似于您的“事务”解决方案),然后将更改记录到库存级别。将大多数更改更新到库存级别应该不会太难,以便它们也留下交易记录。您还可以添加一个定期任务以每隔几个小时左右将库存级别备份到事务表中,这样即使您错过了一个事务,您也可以发现更改发生的时间或回滚到以前的状态。

如果您想了解大型应用程序如何查看SugarCRM,他们有库存管理模块,但我不确定它如何存储数据。

于 2008-11-13T15:07:26.717 回答
4

我认为这实际上是一个一般的最佳实践问题,关于每次需要总数时进行(相对)昂贵的计数与每次发生变化时进行计数,然后将计数存储在字段中并在需要时读取该字段全部的。

如果我不能使用事务,我会在每次需要总数时使用实时计数。如果交易可用,则可以安全地执行库存更新操作并在同一交易中保存重新盘点的总数,这将确保计数的准确性(尽管我不确定这是否适用于多个用户打数据库)。

但是,如果性能不是一个真正的大问题(并且现代数据库在计算行数方面足够好,我什至很少担心这一点),我每次都会坚持使用实时计数。

于 2008-11-13T15:32:23.547 回答
3

我会选择第一种方式,在哪里

现有数量是根据收到的总库存计算的 - 已售库存的总和

正确的方式,国际海事组织。

编辑:我还想将系统中的任何库存损失/损坏考虑在内,但我相信你已经涵盖了。

于 2008-11-13T14:46:10.737 回答
2

我以前研究过解决这个问题的系统。我认为理想的解决方案是预先计算的列,它可以让您两全其美。您的总数将是某处的一个字段,因此无需昂贵的查找,但它不能与您的其余数据不同步(数据库保持完整性)。我不记得哪些 RDMS 支持预先计算的列,但如果您没有事务,那也可能不可用。

您可能会使用触发器伪造预先计算的列(非常有效......我认为没有缺点)。不过,您可能需要交易。恕我直言,在进行这种受控非规范化时保持数据完整性是触发器的唯一合法用途。

于 2008-11-13T16:31:01.603 回答
2

Django-inventory更适合固定资产,但可能会给你一些想法。

IE:ItemTemplate(类)-> ItemsOnHand(实例)

ItemsOnHand 可以链接到更多的 ItemTemplates;示例打印机和墨盒是必需的。这也允许为每个 ItemOnHand 设置重新订购点。

每个 ItemsOnHand 都链接到 InventoryTransactions,这样便于审计。为了避免从数千个库存交易中计算实际的现有项目,使用了只是余额 + 日期的检查点。计算手头上的项目以查找最近的检查点并开始添加或减去项目以查找当前的项目余额。定期定义新的检查点。

于 2009-10-03T05:22:35.177 回答
1

我可以看到拥有两列的一些好处,但我没有关注关于差异的部分 - 您似乎暗示拥有两列(进出)比单列(当前)更不容易出现差异。这是为什么?

于 2008-11-13T15:10:44.760 回答
0

没有一两列,我的意思是“收到的总库存 - 售出的总库存”是这样的:

Select sum(quantity) as inventory_received from Inventory_entry
Select sum(quantity) as inventory_sold from Sales_items

然后

Qunatity_on_hand = inventory_received - inventory_sold

请记住,我过度简化了这一点和我最初的解释。我知道库存还有更多只是跟踪数量,但在这种情况下,这就是问题所在,也是我们想要解决的问题。此时改变它的原因恰恰是支持当前设计引起的问题的成本。

我还想提一下,虽然这不是“编码”问题,但与算法和设计有关,恕我直言,这是非常重要的主题。

到目前为止,感谢大家的回答。

纳尔逊马尔莫尔

于 2008-11-13T15:39:18.743 回答
0

我们解决不同的问题,但我们处理其中一些问题的方法可能会让您感兴趣。

我们允许系统做出“最佳猜测”,并定期向用户提供关于任何看起来错误的猜测的反馈。

要将其应用于库存,您可以有 3 个字段:

inventory_received
inventory_sold
estimated_on_hand

然后,您可以按照以下方式运行一个流程(每天?):

SELECT * 
FROM   Inventory
WHERE  estimated_on_hand != inventory_received - inventory_sold

当然,这取决于用户查看此警报并对其采取措施。

此外,您可以通过更新inventory_sold/received 或添加另一个字段“inventory_adjustment”来以某种方式重置库存,这可能是正数或负数。

...只是一些想法。希望它有帮助。

于 2008-11-13T15:55:11.083 回答