2012-03-11 138 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行仍然存在),然後從該行獲取你想要的任何信息。