2

これは図書館管理システム用です。

私は2つのテーブルを持っています、1つはBooksフィールド付きですBookId, Title, AuthorId, PublisherId, ISBN, ISBN13, PublishedOn, NumberOfPages, etc etc.

その他はBookTransactions、フィールドを使用して、任意の学生に発行された、または任意の学生から受け取った本のすべてのトランザクションを含むものです。TransactionId, BookId, IssuedOn, IssuedTo, ReceviedOn, etc. etc.

問題は、私がこの本を持っていてThe God Delusion、200部あるとしましょう。テーブルのエントリは次のBooksようになります

7  The God Delusion  21  32  0618680004  978-0618680009 .....
8  The God Delusion  21  32  0618680004  978-0618680009 .....
9  The God Delusion  21  32  0618680004  978-0618680009 .....
10 The God Delusion  21  32  0618680004  978-0618680009 .....
.
.
.

(200行)。他のすべてはまったく同じです。各本に200のエントリがあるだけです。これで、という名前の列を作成できることがわかりましQuantityたが、これを聞いてください(それが質問の理由です)

しばらくするとテーブルBookTransactionsはこんな感じになるかもしれません

1   9    4/3/2012   ABC   __  
2   10   4/3/2012   PQR   __  
3   7    4/3/2012   XYZ   7/3/2012

したがって、3冊の「神の妄想」の本が同じ日に発行されたことを明確に示しています。利点は、ブック番号7が発行されているかどうかを確認できることです。発行されていない場合は、次のように発行できます。

sqlCommand.CommandText = "SELECT Count(*) FROM BookTransactions WHERE BookId=7 AND ReceivedOn is NULL";
// if a book is received, its in library and can be issued again
if (Int32.Parse(sqlCommand.ExecuteScalar().ToString()) == 0)
    bookInstance.IssueThisBook();
else
   MessageBox.Show("This book is already issued to someone, please select a different book");

ここで、列の数量を持つことの問題は、Booksテーブルが次のようになったかどうかということです。

7  The God Delusion  21  32  0618680004  978-0618680009 ..... 200 
// the last one indicates quantity

今のエントリは次のBookTransactionようになります

1   7    4/3/2012   ABC   __

そして今、このコードを実行すると、

sqlCommand.CommandText = "SELECT Count(*) FROM BookTransactions WHERE BookId=7 AND ReceivedOn is NULL";
// if a book is received, its in library and can be issued again
if (Int32.Parse(sqlCommand.ExecuteScalar().ToString()) == 0)
    bookInstance.IssueThisBook();
else
   MessageBox.Show("This book is already issued to someone, please select a different book");

1部しか発行されておらず、ライブラリにはまだ199部が残っているにもかかわらず、その本が誰かに発行されていることが示されます。

これを克服する方法はたくさんあることを私は知っています。私が考えることができる1つの方法は、このようなことをすることです。

sqlCommand.CommandText = "SELECT Count(*) FROM BookTransactions WHERE BookId=7 AND ReceivedOn is NULL";
sqlCommandOther.CommandText = "SELECT Quantity FROM Books WHERE Bookid=7"
// if the count is not equal to total quantity then there are some books availabe in libray
if (Int32.Parse(sqlCommand.ExecuteScalar().ToString()) != Int32.Parse(sqlCommandOther.ExecuteScalar().ToString()))
    bookInstance.IssueThisBook();
else
// all books are currently issued
   MessageBox.Show("All copies of this book are already issued, please select a different book");

ええと、これが私が考えることができる唯一の方法ですが、これは効率的ではないことを知っています。200部あるという理由だけで、本に200行あるというこの冗長性を取り除くことができる別の方法があるのでしょうか。(そして、前の段落で説明した以外の方法を意味します。)私がやろうとしていることを達成するための最良の方法は何でしょうか。
私は自分自身を明確にしたいと思います。

StarPilotのポイントを編集することは注目に値します本当に200の異なる行/レコードが必要ですか?彼が指摘したように、特定の本、たとえば#50が紛失または破損していないかどうかを追跡するにはどうすればよいですか?これを部分的に取り入れると、冗長性が必要なように見えますよね?

4

5 に答える 5

4

本(タイトル)とコピーを区別する必要があります。つまり、持っている必要があります

  1. 書籍に関する情報を含み、書籍ごとに 1 つの行しかない書籍のテーブル。

  2. コピー用のテーブル。これには、書籍ごとに、所有しているコピーの数と同じ数の行が含まれます (できれば、あるコピーを他のコピーと区別できるシリアル番号が付けられます)。BookId を外部キーとして持ちます。

  3. 外部キーとして CopyId を持つトランザクションのテーブル。

于 2012-07-31T17:50:04.193 に答える
1

それはあなたがこのデータで何をする必要があるかにかなり依存します。

発行する特定のタイトルの本が残っているかどうかだけを気にする場合はBooks、本を発行するたびにデクリメントし、返却するたびにインクリメントできるという点で、行ったことを正確に実行し、数量フィールドを使用できます。追加のコピーが残っているかどうかを知るには、カウンターがゼロより大きいかどうかを知る必要があります。現在発行されている本の数も追跡する必要がある場合は、元の数量をBooksテーブルに保持し、それを使用して現在の数と比較することもできます。

書籍の個々のコピーを追跡する必要があると思われる場合でも、書籍のすべての不変データをBooksテーブルに保持し、BookInstanceテーブル(またはそのようなもの)を使用して保持することで、多くの冗長性を取り除くことができます。個々のインスタンスを追跡します。そうすれば、発行トランザクションを書籍の個々のインスタンスにリンクできますが、元のデザインに含まれるすべての冗長データを持ち歩くことはできません。

于 2012-07-31T17:51:23.680 に答える
1

次のようにデータベースを構築してみてください。

Book { BookId, Title, AuthorId, PublisherId, ISBN, ISBN13, PublishedOn, NumberOfPages, etc }
BookStock { BookStockId, BookId, StockDateTime }
BookCheckOut { BookCheckOutId, BookStockId, CheckOutDate, CheckInDate, Quantity }

テーブルは本BookStockごとに 1 つの行をBookCheckOut保持し、チェックアウトが発生するたびにテーブルは新しい行を保持します。したがって、次のクエリで在庫数を調べるのは簡単です。

SELECT COUNT(bs.BookStockId) - (SELECT COUNT(bco.BookCheckOutId) FROM BookCheckOut bco WHERE bco.BookStockId = bs.BookStockId AND bco.CheckInDate IS NULL) FROM BookStock bs

actualさらに、このクエリでチェックアウトされたすべての本を取得するのは非常に簡単です。

SELECT * FROM BookCheckOut WHERE BookStockId = {id} AND CheckInDate IS NULL

そして最後に、本の重複を削除しました。データベースには 1 回しかありません。一般的に言えば、在庫を扱うときは、数量だけでなくすべての取引を追跡する必要があります。少し過剰に設計されているように感じるかもしれませんが、BookStock後でテーブルを簡単に使用して誰が在庫したかを確認したり、バーコード スキャンを使用して ISBN 番号をスキャンして書籍を在庫したりすることもできます。ISBN 番号をスキャンし、それで本を検索し、BookStockテーブルに行を追加するだけで在庫が追加されたことを想像してみてください。

ああ、最後に、バーコード スキャンを使用して非常に簡単にチェックインBookCheckOutできるようになりましたBook

于 2012-07-31T17:56:15.153 に答える
0

別のテーブルが必要です - それを BookMaster と呼んでください。これには、ID と、書籍に関するすべての共通データ (タイトル、著者など) が含まれます。現在の Books テーブルには、2 つのテーブルを接続する BookMasterId 列があります。これで、「The God Delusion」の BookMaster レコードが 1 つになり、200 の Book レコードが残るため、個々のコピーを追跡できます。

于 2012-07-31T17:50:26.793 に答える
0

さまざまなコピーを追跡するために、新しいテーブル「BookCopies」を提案します。CopyNumber、BookID (デュアル プライマリ キー)、およびステータス「利用可能、紛失など」のようなもの

次に、時間の経過とともに非常に大きくなる可能性が高い Transactions テーブルの代わりに、コピー テーブルに対してクエリを実行して、availble ステータスを取得できます。

于 2012-07-31T17:59:51.990 に答える