これは、実際には「プログラミング」に関する質問ではなく(言語やデータベースに固有のものではありません)、デザインとアーキテクチャに関する質問です。また、「Xを実行する最善の方法」というタイプの質問でもあります。多くの「宗教」論争の原因にならないことを願っています。
過去に、何らかの形でアイテムの在庫を保持するシステムを開発しました(関連するアイテムはありません)。トランザクションをサポートしない言語/ DBを使用しているものもあります。そのような場合、アイテムレコードのフィールドにアイテム手持数量を保存しないことを選択しました。代わりに、手持数量は、受け取った在庫の合計-販売した在庫の合計を計算します。これにより、ソフトウェアによる在庫の差異はほとんどありません。テーブルは適切にインデックス付けされ、パフォーマンスは良好です。レコードの量がパフォーマンスに影響を与え始める場合のアーカイブプロセスがあります。
数年前、私はこの会社で働き始め、在庫を追跡するシステムを継承しました。ただし、数量はフィールドに保存されます。エントリが登録されると、受け取った数量がアイテムの数量フィールドに追加されます。アイテムが販売されると、数量が差し引かれます。これにより、矛盾が生じました。私の意見では、これは正しいアプローチではありませんが、以前のプログラマーはそれを誓います。
そのようなシステムを設計するのが正しい方法であるかについてコンセンサスがあるかどうかを知りたい。また、これに関するガイダンスを求めるために、印刷またはオンラインで入手可能なリソース。
ありがとう
私は現在の会社で両方のアプローチを見てきましたが、間違いなく最初のアプローチ(株式取引に基づいて合計を計算する)に傾くでしょう。
どこかのフィールドに合計数量のみを保存している場合、その番号にどのように到達したかわかりません。トランザクション履歴はなく、問題が発生する可能性があります。
私が書いた最後のシステムは、各トランザクションを正または負の数量を持つレコードとして保存することにより、在庫を追跡します。私はそれが非常にうまくいくことを発見しました。
在庫システムは、アイテムを数えるだけではありません。たとえば、会計目的で、FIFO(先入れ先出し)モデルに基づいて在庫の会計値を知る必要がある場合があります。これは単純な「在庫の合計受け取った-在庫の合計」という式。しかし、彼らはモデルがこれを簡単に計算するかもしれない。彼らは会計値を変更するので。これはプログラミングの問題ではないので詳細に行きたくない対処しなければならない要件を完全に理解していませんでした。
状況に応じて、両方とも有効です。前者は、次の条件が当てはまる場合に最適です。
一方、多数のアイテム、いくつかの例外的なケース、頻繁なアクセスがある場合、アイテムの数量を維持する方が効率的です。
また、システムに矛盾がある場合はバグがあるを追跡して排除する必要があることに注意してください
両方の方法でシステムを実行しましたが、バグを無視しない限り、両方の方法で問題なく動作します!
ARTS(Association for Retail Technology Standards)データモデル( http://nrf-arts.org )をご覧ください。各アイテムのレコードを含むStockLedgerテーブルを使用し、インベントリへの変更はすべてInventoryJournalEntriesで追跡されます。
これは実際には、合計が必要になるたびに(比較的)高価なカウントを行うことと、何かが変わるたびにそのカウントを行うこと、そして必要に応じてフィールドにカウントを保存することに関する一般的なベストプラクティスの質問だと思います合計。
トランザクションを使用できない場合、合計が必要になるたびにライブカウントを使用します。トランザクションが利用可能な場合、同じトランザクション内でインベントリ更新操作と再カウントされた合計を保存しても安全です。これにより、カウントの正確性が保証されます(ただし、複数のユーザーで機能するかどうかはわかりませんが)データベースにアクセスします)。
しかし、パフォーマンスが実際に大きな問題ではない場合(そして、最新のデータベースで行のカウントが十分であるため、このことを心配することもめったにない場合)、毎回ライブカウントを維持します。
既存のシステムと、それを変更するコストとリスクを考慮することが重要です。私はあなたのようなインベントリを保存するデータベースを使用していますが、監査サイクルが含まれており、レシートと同様に調整が保存されています。うまく機能しているように見えますが、関係者全員はよく訓練されており、倉庫のスタッフは新しい手順をすぐに学ぶことができません。
あなたの場合、データベース構造全体を変更せずにもう少し追跡したい場合は、追跡テーブル(「トランザクション」ソリューションのようなもの)を追加してから、変更をインベントリレベルに記録することをお勧めします。在庫レベルへのほとんどの変更を更新して、トランザクションレコードも残すようにするのはそれほど難しくないはずです。定期的なタスクを追加して、数時間ごとにインベントリレベルをトランザクションテーブルにバックアップすることもできます。これにより、トランザクションを逃した場合でも、変更がいつ発生したか、以前の状態にロールバックできます。
大規模なアプリケーションがどのように SugarCRM を見ているかを確認したい場合、データをどのように保存するかわかりませんが、インベントリ管理モジュールがあります。
私は最初の方法を選びます
手持ちの数量は、受け取った在庫の合計-販売した在庫の合計を計算します
正しい方法、IMO。
編集:また、システムへの在庫の損失/損傷も考慮したいと思いますが、それがカバーされていると確信しています。
Django-inventory 固定資産を対象としていますが、いくつかのアイデアが得られるかもしれません。
IE:ItemTemplate(クラス)-> ItemsOnHand(インスタンス)
ItemsOnHandは、より多くのItemTemplateにリンクできます。例プリンターとインクカートリッジが必要です。これにより、各ItemOnHandにリオーダーポイントを設定することもできます。
各ItemsOnHandはInventoryTransactionsにリンクされているため、簡単に監査できます。数千の在庫トランザクションから実際の手持ちアイテムを計算することを避けるために、残高と日付だけのチェックポイントが使用されます。手持ちアイテムクエリを計算して最新のチェックポイントを見つけ、アイテムの追加または減算を開始してアイテムの現在の残高を見つけます。新しいチェックポイントを定期的に定義します。
私は以前にこの問題を解決するシステムに取り組んできました。理想的なソリューションは、両方の長所を活用できる事前計算されたコラムだと思います。合計はどこかのフィールドになるため、高価なルックアップはありませんが、他のデータと同期を取ることはできません(データベースは整合性を維持します)。どのRDMSが事前に計算された列をサポートしているかは覚えていませんが、トランザクションがない場合は利用できない可能性があります。
トリガーを使用して、事前に計算された列を偽造する可能性があります(非常に効果的に...マイナス面はありません)。ただし、おそらくトランザクションが必要でしょう。私見では、この種の制御された非正規化を行っているときにデータの整合性を維持することが、トリガーの唯一の正当な使用です。
2つの列を持つことにはいくつかの利点がありますが、矛盾については説明していません-2つの列(インとアウト)を持つことは、1つの列(現在)よりも矛盾しない傾向があることを暗示しているようです。何故ですか?
1つまたは2つの列がありません。「受け取った在庫の合計-販売された在庫の合計」とは、次のようなものです。
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
これと私の最初の説明を単純化しすぎたことに留意してください。在庫を管理するだけでなく、数量を追跡するだけではないことはわかっていますが、この場合は問題の嘘であり、修正したいものです。この時点で変更する理由は、正確には現在の設計によって引き起こされる問題をサポートするためのコストです。
また、これは「コーディング」の質問ではありませんが、アルゴリズムとデザインに関連するものですが、私見は非常に重要なトピックです。
これまでの回答に感謝します。
ネルソン・マーモル
私たちはさまざまな問題を解決しますが、それらのいくつかに対する私たちのアプローチはあなたにとって興味深いかもしれません。
システムが「最良の推測」を行うことを許可し、間違っていると思われる推測についてユーザーに定期的なフィードバックを提供します。
これを在庫に適用するには、3つのフィールドがあります。
inventory_received
inventory_sold
estimated_on_hand
次に、次の行に沿ってプロセスを実行できます(毎日?)。
SELECT *
FROM Inventory
WHERE estimated_on_hand != inventory_received - inventory_sold
もちろん、これはユーザーがこのアラートを見て、それについて何かをすることに依存しています。
また、inventory_sold/receivedを更新するか、別のフィールド「inventory_adjustment」を追加することにより、何らかの方法で在庫をリセットする機能を使用できます。
...いくつかの考え。役に立てば幸いです。