2

我正在为我的学校设计一个图书馆应用程序。我们有 2-3 个主要图书馆,有些部门有自己的图书馆。我想知道这些查询是否正确?

Libraries 
ID Name
1  Walter
2  Wally
3  Maths dept library

Books
ID Book ID  BookName
1   1       Fundamentals of calculus
2   1       Mechanics 
3   2       Fundamentals of calculus
4   2       Biology

Lib_Book_LookUp
ID  libId bookId
1    1     1
2    1     2
3    2     1
4    2     2

我想解决的两个问题是:

  1. 查找特定书籍的副本数
  2. 找出哪些图书馆有一本特定的书

这是我所拥有的:

Select count(Book.bookId) where book.name = "Fundamentals of calculus";

Select count(libId) from Lib_Book_lookUp, Book where Book.BookId = Lib_Book_lookUp.bookId groupBy(libId)

我对这些查询的问题:

  1. 似乎没有必要有一个单独的查找表并将 libId 合并到 Books 表中并将其作为 book 表上的外键?
  2. 查询似乎正确吗?
4

3 回答 3

4

您的第一个查询缺少一个FROM子句。您也可以这样做COUNT(*),但在这种情况下并不特别重要:

 SELECT count(Book.bookId) FROM Books WHERE BookName = "Fundamentals of calculus";

要找出哪些图书馆有一本特定的书,您不需要COUNT()汇总。相反,您需要一个WHERE带有连接的子句。会COUNT()告诉你有多少图书馆有一本书,而不是哪些图书馆。为此,您需要一个返回的查询Libraries.Name

SELECT
  /* Return library names */
  Libraries.Name
FROM 
  Libraries 
  /* Join through your lookup table to match a book name to a library name */
  JOIN Lib_Book_LookUp ON Libraries.ID = Lib_Book_LookUp.libId
  JOIN Books ON Books.ID = Lib_Book_LookUp.bookId
/* Which book to search for */
WHERE Books.BookName = 'Fundamentals of calculus'

Books查找表是合适的,因为如果它存在于多个图书馆中,它允许您将书籍规范化为表中的单个记录。正如你所拥有的,没有真正的理由在Books表中有多个副本,也没有理由在Book ID列中。实际上,该Book ID列本身具有很大的误导性。有两个不同标题的书具有相同的 id 1

Books表实际上应该如下所示,每个书名有一条记录(假设标题为权威,忘记像 ISBN 之类的真正权威的东西)

Books
ID BookName
1  Fundamentals of calculus
2  Mechanics 
3  Biology

如果您在每个图书馆可能有每本书的多个副本,您可以考虑将每个副本的书籍标准化为一个通过图书馆条形码标识它们的表格。然后,您将这些 id 与图书馆相匹配作为馆藏:

Books (defines bibliographic details)
ID BookName
1  Fundamentals of calculus
2  Mechanics 
3  Biology

Book_Copies (Matches Books.ID to barcode, barcode is Primary Key)
BookId Barcode
1      1234567
1      1234568
2      8654321
2      8654322

Lib_Book_LookUp (matches book copies to libraries, allowing multiple copies by barcode)
ID  libId bookBarcode
1    1     1234567
2    1     1234568
3    2     8654321
4    2     8654322

例如,要查询每个图书馆每本书的副本数,您可以使用:

SELECT 
  Libraries.Name,
  Books.BookName,
  COUNT(*)
FROM 
  Libraries
  JOIN Lib_Book_LookUp ON Libraries.ID = Lib_Book_LookUp.libId
  JOIN Book_Copies ON Lib_Book_Lookup.bookBarcode = Book_Copies.Barcode
  JOIN Books ON Book_Copies.BookId = Books.ID
GROUP BY 
  Libraries.Name, 
  Books.BookName
于 2012-10-15T13:54:40.820 回答
1

关于您的数据库设计,您不需要在查找表上有代理键。您可以像这样简单地做一个图书馆和书的复合主键:

Lib_Book_LookUp
libId bookId
1 1
1 2
2 1
2 2

我对您的图书 ID 进行了以下更改(力学和生物学具有相同的 ID):

图书
ID Book ID BookName
1 1 微积分基础
2 2 力学
3 1 微积分基础
4 3 生物学

在您的第一个查询中,您没有指定语句引用的表 ( FROM books):

SELECT COUNT(bookId)
FROM books                                       <= Table Reference
WHERE BookName = "Fundamentals of calculus";

在第二个查询中,您使用隐式语法来连接表。您应该像这样练习显式连接:

SELECT Lib_Book_LookUp.libId, Libraries.Name
FROM Lib_Book_LookUp
INNER JOIN Libraries ON Libraries.ID = Lib_Book_LookUp.libId
WHERE bookId IN 
    (SELECT DISTINCT bookId
    FROM books
    WHERE BookName = "Fundamentals of calculus")

此查询连接LibrariesandLib_Book_LookUp表,然后查找具有bookId正在搜索的图书的图书馆。

看到它在行动

于 2012-10-15T14:12:36.803 回答
-1

您的 books 表看起来更像是“Instances of a book”表。因此,它不应该有书名。要么,要么BookID列是多余的。

如果您从 1988 开始编写 SQL,那么您的第二个查询是正确的。如果没有,您应该使用join语法。

于 2012-10-15T13:56:15.987 回答