如何在表格中删除此冗余?

时间:2012-07-31 17:43:52

标签: c# sql-server database database-design relational-database

这适用于图书馆管理系统。

我有两个表,一个是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是丢失还是损坏?将此视为部分看起来确实必须有冗余,对吗?

5 个答案:

答案 0 :(得分:4)

您必须区分书籍(标题)和副本。这意味着你应该

  1. 书籍表,其中包含有关书籍的信息,每本书只有一行;

  2. 副本表,每本书包含尽可能多的副本(最好有一些序列号,允许你告诉其他副本),将BookId作为外键

  3. 表格中包含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表。