Microsoft Access 掲示板

レコードを削除するか削除フラグフィールドを追加するか

4 コメント
views
4 フォロー

いつもお世話になっております。
キャンセルになった注文データをテーブルから削除してしまうか、フラグを付けてレコードを残すか迷っています。

現行のシステム
1.CSVから注文データを取り込む
2.現物票を印刷する(現物票出力日フィールドを本日日付に更新
3.出庫する(出庫日フィールドを本日日付に更新)
4.梱包する(梱包明細出力日フィールドを本日日付に更新)
現物票出力日・出庫日・梱包明細出力日全てに日付が入力されていれば出荷済み扱いになります。

現物票未出力・未出庫・未梱包それぞれの件数を、抽出条件Nullでカウントするクエリを作成しようとしていたところ、
注文がキャンセルになり出庫日や梱包明細出力日が入力されないまま放置されているレコードが存在していることがわかりました。

キャンセル分の注文をカウントの対象から外すにはテーブルからレコードを消す(又は別テーブルに移動させる)か、抽出条件でフラグが立っているものを含まないようにするかの2択だと思うのですが、皆様はどちらの方法を採用するのが良いと考えますか?

現在のレコード数が約5万件、うち出荷済み扱いになっていないのが約1500件、注文データの追加は月2~300件程度です。
キャンセルになった注文をデータベース上で後日確認したり、復活させることはまずありません。
このデータベース上のほとんどのクエリはこの注文データテーブルが使われています。
こちらを参考にどちらが良いか考えてみたのですがいまいち判断がつかないため、皆様のご意見をお聞かせ下さい。

驚天動地!前任者失踪丸
作成: 2024/05/20 (月) 13:02:47
通報 ...
1
hiroton 2024/05/20 (月) 16:32:16 dc926@f966d

「既存のデータベースであり、キャンセルのフラグがある」なら、キャンセルを抽出条件に使います。すでに運用中であり、仕様を完全に把握しているのでなければ、データの削除に対する影響がわかりません

「既存のデータベースであり、キャンセルのフラグがない」なら、集計に含まないとする条件をそれぞれ追加するしかないでしょう

「既存のデータベースであり、キャンセルを削除する」を考えた場合、今後の運用に問題はないでしょうか?それを正しく削除できますか?誰が、いつ、できますか?


hirotonの場合、設計段階として、Nullを数えるような仕組みを極力排除します。仕組みとしては、「現物票出力日」「出庫日」「梱包明細出力日」の他に「状態」フィールドを設け、「-1;キャンセル;0;現物票未出力;1;未梱包;2;未出庫;3;出庫済み」とします。明確に目的のものを集計するのでミスが起こりません
キャンセルについては、「梱包まで済んでキャンセルになった」のようなそれをどうするんだ?という場合もあると思います。要求に合わせて「受注状態(キャンセル・受注・納品済み)」「作業行程(伝票未発行、未梱包、未出庫、出庫済み)」のように、複数フィールドで管理する場合もあります

-1からの連番にしてしまっているので設計段階で工程をしっかり把握しておく必要があることには注意が必要です。「状態マスタ」テーブルを作成して、数値に意味を持たせないのが正しい正規化ですが、末端の情報にそこまで神経質になって後から良かったと感じたことはそれほどないです


当たり前ですが、削除すべきデータは削除します(ミス登録とか)
「キャンセル」というアクションは「存在しなかったもの」として扱っていいモノでしょうか?そうであるならば、「キャンセル」というアクションが起きたときにデータを削除するようにすればいいです
「とりあえず削除フラグ」というやり方は削除フラグが問題の原因ではなく、「とりあえず」という妥協する姿勢が問題になるのです


現在のレコード数が約5万件、うち出荷済み扱いになっていないのが約1500件

およそ3%が問題のデータということですが、パフォーマンスが問題になった場合、不要分のデータが存在しなかったとするならば、問題が発生するまでの期間の3%の期間だけ延命できることになります
パフォーマンスが問題になるならば、もっと根本的な解決が必要です

2

キャンセルになった注文をデータベース上で後日確認したり、復活させることはまずありません。

「まずありません」ということは「絶対ない」ではない「わずかであるがありうる可能性がある」ということですよね。
Accessデータベースはファイルサイズ2GBの制限がありますが、それに達する可能性がないのなら、私なら削除せずに「削除フラグ」を立てておくという方法をとりますね。
インデックスを適切に設定されているなら、パフォーマンスにほとんど影響はないと思いますので。

OSに実装されている「ごみ箱」の機能と同等のもの実装するということをしたことがあります。下記でサンプルを紹介していますのでご参考に。

削除したレコードを復活できる「ごみ箱」の設計
Accessでは削除したレコードは基本的には復活できません。削除する前に確認するようにしても、つい、うっかりと削除してしまう場合や、必要ないと思い削除しても後で必要になる場合もあったりします。 OS のごみ箱のように、いったんごみ箱へ移動しておいて、必要になったらまた復活させることができると便利ですね。テーブル単体では無理ですが、フォームから入力、削除するようにすれば、比較的簡単に実現できます。 ...
Fc2

上記のサンプルでは削除日時フィールドを追加して、それがNullのレコードは生きているレコードと、日時が入力されいいるレコードは削除レコードとしています。
こうしておけば、例えば削除後X年経過したら自動的にテーブルから削除するとか、削除してもいいか確認するとか、、、運用に合わせてお好みに設計できます。

3

質問のリンク先
論理削除はアンチパターンなのか? #MySQL - Qiita
で提示されているデメリットについて今回の案件で検討してみます。

パフォーマンスへの影響
現在レコード数が約5万件、月2~300件程度の追加、削除(キャンセル)件数3%程度

このぐらいのデータ件数なら、削除フラグフィールドにイデックスを設定しておけば、ほとんど影響ないとかんがえていいと思います。

クエリの複雑化
Accessではクエリはテーブルと同等に扱えます。
上記の回答でしたように、論理削除レコードを除いたクエリを作成しておいて、それを使えば、現象のクエリやフォーム、レポートの修正する必要はありません。
クエリも複雑化しません。

ユニーク制約に工夫が必要
リンク先ではusersテーブルのメールアドレスにユニーク制約(Accessでは「重複なしのインデックス」)を設定する場合を例に挙げてますが、おそらく今回の注文テーブルではそのようなフィールドはないのではないかと。
あったとしても、私の回答の方法では削除日時をフラグフィールドにしているので、複数フィールドインデックスでユニーク制約の設定は可能です。

ということで、今回の要件なら大きなデメリットはないかと思います。

4
驚天動地!前任者失踪丸 2024/05/24 (金) 08:21:21 23e8e@44ebd

返信が遅くなり申し訳ありません。
hirotonさん、Hatenaさんりがとうございました。
テーブル内に取消日というフィールドがあったので、そこに日付を入れる形で論理削除にしようと思います。