2012-03-11 128 views
0

我正在开发一个网站,它将托管我自己编写的许多书籍。书籍内容将作为HTML块存储在数据库中。需要帮助重构查询/数据库设计

一本书包含多个章节,每章包含几个章节。我决定给每本书,章节和章节唯一的ID:s,目的是我可以自由移动和删除部分,而不必更新记录。

因此数据库看起来是这样的:“世界,你好”

books: 
    book_id int 
    book_name varchar 

chapters: 
    book_id int references books.book_id 
    chapter_id int 
    chapter_no int 
    chapter_name varchar // will probably be factored out to a separate table 

sections: 
    chapter_id int references chapters.chapter_id 
    section_no int 
    section_id int references section_texts.section_id 

section_texts: 
    section_id int 
    section_text text 

因此,例如在第3章第5节可以指向具有section_id 79,并包含文本section_text。第6节可能有section_id 83等。

现在我想创建一个PHP方法,它会给出书名,章节号和章节号,为我检索section_text。我现在已经是在4个步骤进行:

function getText($bookName, $chapter, $section) 
{ 
    // retrieve book id 
    $query = $this->db->query(
     sprintf('SELECT book_id 
      FROM books` 
      WHERE book_name = %s;', $bookName)); 

$row = $query->row(); 
$bookId = $row->book_id; 

// retrieve chapter id 
$query = $this->db->query(
     sprintf('SELECT chapter_id 
      FROM chapters` 
      WHERE book_id = %d AND chapter_no = %d;', $bookId, $chapter)); 

$row = $query->row(); 
$chapterId = $row->chapter_id; 

// retrieve section id 
$query = $this->db->query(
     sprintf('SELECT section_id 
      FROM sections` 
      WHERE chapter_id = %d AND section_no = %d;', $chapterId, $section)); 

$row = $query->row(); 
$sectionId = $row->section_id; 

// retrieve section text 
$query = $this->db->query(
     sprintf('SELECT section_text 
      FROM section_texts` 
      WHERE section_id = %d;', $sectionId)); 

$row = $query->row(); 
return $row->section_text; 
} 

因此,对于我们上面的例子,呼吁getText("testBook", 3, 5)应该返回检索到的文本,这是Hello World!

虽然它有效,但它似乎是错误的方式,创建4个查询来获取一个部分。这将是一个小型网站,所以表现不是问题,但我仍然对如何改进这个问题感兴趣。

回答

1

你应该看看的函数称为“JOIN”,它允许你在一个语句中逻辑连接两个表。 (见MySQL ReferenceWikipedia: JOIN)所以,你的例子可能看起来像下面这样:

SELECT section_texts.section_text 
    FROM section_texts st 
     JOIN sections s ON st.section_id = s.section_id 
     JOIN chapters c ON s.chapter_id = c.chapter_id 
     JOIN books b ON c.book_id = b.book_id 
    WHERE b.book_id = <book-id> 
     AND c.chapter_no = <chapter> 
     AND s.section_no = <section>; 

最后,我没有看到一个理由单独的章节和section_texts。为了保存一个JOIN操作(并且因为它是一个关于同一个实体的1:1关系),尝试将section_text-Column合并到sections表中,从而删除section_texts-Table。

希望有帮助!

+0

谢谢。我担心的是以下情况。假设在一章中我有第1,2,3节。第1节包含文本A,第2节包含文本C,第3节包含文本D.但oops,我意识到我需要插入另一个包含文本B的节,它应该被放置在当前的第1部分和第2部分之间。因此,我想不必重新洗牌其他部分中的文本。 – 2012-03-11 10:27:42

1

因此,从名称所需的书开始,如果章节与给定章节相匹配,则将章节放在该书上,然后如果章节ID与给定章节匹配,则将章节连接到该章节,然后选择html来自该部分。

可视化..从所有书籍开始,过滤除你想要的书外的所有内容,然后加入所有章节,并过滤出你想要的章节(让你再次留下一行),然后加入所有章节,并过滤出你想要的部分(再次,1行仍然存在),然后从该行获取你想要的任何信息。