2012-03-11 4 views
0

Я работаю над сайтом, на котором будет размещено несколько книг, написанных мною. Содержимое книги будет храниться как фрагменты HTML в базе данных.Нужна помощь в рефакторинге запросов/создании базы данных

Книга содержит несколько глав, и каждая глава содержит несколько разделов. Я решил предоставить уникальные идентификаторы каждой книги, главы и раздела: с целью свободно перемещать и удалять разделы и не обновлять записи.

Так база данных выглядит следующим образом: «Привет, мир!»

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 

Так, например, раздел 5 в главе 3, можно указать на section_text, который имеет section_id 79, и содержит текст. Раздел 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 Reference или Wikipedia: 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 в таблицу разделов, тем самым отменив section_texts-Table.

Надеюсь, что это поможет!

+0

Спасибо. Меня волнует следующий сценарий. Предположим, что в главе у меня есть разделы 1, 2, 3. Раздел 1 содержит текст A, раздел 2 содержит текст C, раздел 3 содержит текст D. Но я понял, что мне нужно вставить другой раздел, который имеет текст B, и он должен быть размещены между тем, что является текущим разделом 1 и 2. Поэтому каким-то образом я хочу иметь возможность не перетасовывать тексты в других разделах. –

1

Итак, начните с книги, которую вы хотите по имени, слева, присоедините главы к этой книге, если глава соответствует данной главе, а затем присоедините секции к этой главе, если идентификатор раздела соответствует данному разделу, затем выберите html из этого раздела.

Для визуализации. Начните со всех книг, отфильтровывайте все, кроме книги, которую хотите, затем присоединитесь ко всем главам и отфильтруйте желаемую главу (оставив вас снова с 1 строкой), затем соедините все разделы , и отфильтруйте требуемый раздел (опять же, останется 1 строка), затем получите любую информацию, которую вы хотите, из этой 1 строки.

Смежные вопросы