这适用于图书馆管理系统。
我有两个表,一个是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'The God Delusion'一书是在同一天发行的。好处是我可以检查是否发出了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");
它会显示该书是发给某人的,即使只发行了一份副本,但库中仍有199份副本。
我知道有很多方法可以解决这个问题,我能想到的一种方法是做这样的事情
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是丢失还是损坏?将此视为部分看起来确实必须有冗余,对吗?
答案 0 :(得分:4)
您必须区分书籍(标题)和副本。这意味着你应该
书籍表,其中包含有关书籍的信息,每本书只有一行;
副本表,每本书包含尽可能多的副本(最好有一些序列号,允许你告诉其他副本),将BookId作为外键
表格中包含CopyId作为外键的交易。
答案 1 :(得分:1)
这取决于你需要对这些数据做些什么。
如果您只关心是否还有任何给定标题的书籍可以发行,您可以完全按照自己的方式行事,并使用Books
中的数量字段,每次出版图书时都可以减少每次返回时都会递增。要知道剩余的副本是否存在,您只需要知道计数器是否大于零。如果您还需要跟踪当前发放的图书数量,您也可以在Books
表中保留原始数量,并使用它来与当前计数进行比较。
如果您认为您需要跟踪图书的每个副本,您仍然可以通过将图书的所有不变数据保留在Books
表中并使用{来删除大量冗余{1}}表(或类似的东西)来跟踪各个实例。这样,您仍然可以将发布的交易链接到各个书籍实例,但不会随身携带原始设计所包含的所有冗余数据。
答案 2 :(得分:1)
尝试按以下方式构建数据库。
Book { BookId, Title, AuthorId, PublisherId, ISBN, ISBN13, PublishedOn, NumberOfPages, etc }
BookStock { BookStockId, BookId, StockDateTime }
BookCheckOut { BookCheckOutId, BookStockId, CheckOutDate, CheckInDate, Quantity }
BookStock
表将为每本书保留一行,每次签出时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
最后,你已经删除了书的重复,它只在数据库中删除过一次。一般而言,在处理库存时,您需要跟踪所有交易而不仅仅是数量。它可能会让您觉得有点过度设计了,但BookStock
表可以在以后轻松地用于存放谁,或者甚至通过扫描ISBN号来使用条形码扫描来存储书籍。想象一下扫描ISBN号码,在那里查找书籍,只需在BookStock
表格中添加一行,然后再添加库存!
哦,最后你可以使用条形码扫描来轻松办理登机手续,因为BookCheckOut
可以轻松导航到Book
和从{{1}}导航。
答案 3 :(得分:0)
您需要另一张桌子 - 称之为BookMaster。它将包括一个id,以及有关该书的所有常见数据,例如标题,作者等。您现在的Books表将有一个BookMasterId列来连接这两个表。然后,您将拥有“The God Delusion”的单个BookMaster记录,并且您仍然可以拥有200本Book记录,因此您可以跟踪每个单独的副本。
答案 4 :(得分:0)
我建议使用新表“BookCopies”来跟踪不同的副本。 CopyNumber,BookID(双主键),可能是状态“可用,丢失等”
然后,您可以针对您的副本表查询可用状态,而不是随时间推移可能非常大的Transactions表。