代码之家  ›  专栏  ›  技术社区  ›  Marcus

如何减少获得此结果所需的查询数

  •  2
  • Marcus  · 技术社区  · 15 年前

    我正在CodeIgniter之上编写一个应用程序,以便更好地组织我的电子书收藏。我差不多完成了,但我意识到我的“浏览”页面运行了太多的查询-每本书两个-来获取他们的信息。显然一点都不理想,尤其是因为我有大约1000本书要放进这个系统。

    我现在有一个模型函数,它获取所有的书(最终将被修改为使用参数——这是下一步),还有一个模型函数获取每个返回的书的元信息。第二个函数是对每本书进行两次查询的函数,一个用于获取图书表中的信息,另一个用于获取与图书相关联的标记。以下是两个模型函数:

    获取书籍列表:

    function get_books() {
        $this->db->select('isbn')->order_by('title');
        $query = $this->db->get('books');
        $result = $query->result();
        return $result;
    }
    

    获取图书元信息:

    function get_book_info($isbn) {
        // Grab the book from Amazon
        $amazon = $this->amazon->get_amazon_item($isbn);
    
        // Get the book info
        $this->db->select('title, publisher, date, thumb, filename, pages');
        $query = $this->db->get_where('books', array('isbn' => $isbn));
        $bookResult = $query->row();
    
        // Get the book's tags
        $this->db->select('tag');
        $this->db->from('tags AS t');
        $this->db->join('books_tags AS bt', 'bt.tag_id = t.id', 'left');
        $this->db->where('bt.book_id', $isbn);
        $this->db->order_by('t.tag');
        $tagQuery = $this->db->get();
        foreach ($tagQuery->result() as $row) {
            $tagResult[] = $row->tag;
        }
        $tagResult = implode(', ', $tagResult);
    
        // Send data
        $data = array(
            'isbn' => $isbn,
            'thumb' => $bookResult->thumb,
            'title' => strip_slashes($bookResult->title),
            'file' => $bookResult->filename,
            'publisher' => strip_slashes($bookResult->publisher),
            'date' => date('F j, Y', strtotime($bookResult->date)),
            'pages' => $bookResult->pages,
            'tags' => $tagResult,
            'rating' => $amazon->Items->Item->CustomerReviews->AverageRating,
            'raters' => $amazon->Items->Item->CustomerReviews->TotalReviews
        );
        return $data;
    }
    

    我确信有一种方法可以编写一个或两个查询,将所有记录收集到我可以过滤的对象中,而不必为每个对象编写两个查询,但我甚至不知道从哪里开始编写。欢迎提出任何建议。

    马库斯

    5 回复  |  直到 15 年前
        1
  •  2
  •   David T. Macknet    15 年前

    您要做的是:

    1. 把你所有的书和标签分类,

    拿上你的书 标签放在一起,有一个变量来跟踪你最后写的ISBN,并且只有当ISBN改变时才建立你的条目。所以,像这样拉一组:

    Book   | Tag
    ------ | ----------------
    Book A | Fiction
    Book A | Fantasy
    Book B | Mystery
    Book C | Science Fiction
    

    然后,写下“基本图书信息”为每一次的书在你的循环变化。显然,您需要的字段不仅仅是 标签 (例如。, ).

        2
  •  1
  •   Marcus    15 年前

    在本主题和其他主题的帮助下,我能够通过以下代码解决此问题:

    function get_book_info() {
    
        /*
         * SELECT b.isbn, b.title, b.publisher, b.date, b.thumb, b.filename, b.pages, t.tag
         * FROM books AS b
         * INNER JOIN books_tags AS bt ON b.isbn = bt.book_id
         * INNER JOIN tags AS t ON bt.tag_id = t.id
         * ORDER BY b.title, t.tag
         */
    
        $this->db->select('b.isbn, b.title, b.publisher, b.date, b.thumb, b.filename, b.pages, t.tag');
        $this->db->from('books AS b');
        $this->db->join('books_tags AS bt', 'b.isbn = bt.book_id', 'inner');
        $this->db->join('tags AS t', 'bt.tag_id = t.id', 'inner');
        $this->db->order_by('b.title, t.tag');
        $query = $this->db->get();
        $result = $query->result();
    
        $counter = '';
        $record = $meta = $tags = array();
        $count = count($result);
        $i = 1;
    
        foreach ($result as $book) {
            // If this is not the last row
            if ($i < $count) {
                // If this is the first appearance of this book
                if ($counter != $book->isbn) {
                    // If the meta array already exists
                    if ($meta) {
                        // Add the combined tag string to the meta array
                        $meta['tags'] = implode(', ', $tags);
                        // Add the meta array
                        $record[] = $meta;
                        // Empty the tags array
                        $tags = array();
                    }
                    // Reset the counter
                    $counter = $book->isbn;
                    // Grab the book from Amazon
                    $amazon = $this->amazon->get_amazon_item($book->isbn);
                    // Collect the book information
                    $meta = array(
                        'isbn' => $book->isbn,
                        'title' => strip_slashes($book->title),
                        'publisher' => strip_slashes($book->publisher),
                        'date' => date('F j, Y', strtotime($book->date)),
                        'thumb' => $book->thumb,
                        'file' => $book->filename,
                        'pages' => $book->pages,
                        'rating' => $amazon->Items->Item->CustomerReviews->AverageRating,
                        'raters' => $amazon->Items->Item->CustomerReviews->TotalReviews
                    );
                    // Add the tag to the tags array
                    $tags[] = $book->tag;
                } else {
                    // All we need is the tag
                    $tags[] = $book->tag;
                }
            // If this is the last row
            } else {
                // If this is the first appearance of this book
                if ($counter != $book->isbn) {
                    // Grab the book from Amazon
                    $amazon = $this->amazon->get_amazon_item($book->isbn);
                    // Collect the book information
                    $meta = array(
                        'isbn' => $book->isbn,
                        'title' => strip_slashes($book->title),
                        'publisher' => strip_slashes($book->publisher),
                        'date' => date('F j, Y', strtotime($book->date)),
                        'thumb' => $book->thumb,
                        'file' => $book->filename,
                        'pages' => $book->pages,
                        'rating' => $amazon->Items->Item->CustomerReviews->AverageRating,
                        'raters' => $amazon->Items->Item->CustomerReviews->TotalReviews
                    );
                    // Add the tag to the tags array
                    $tags[] = $book->tag;
                    // Add the combined tag string to the meta array
                    $meta['tags'] = implode(', ', $tags);
                    // Add the meta array
                    $record[] = $meta;
                } else {
                    // All we need is the tag
                    $tags[] = $book->tag;
                    // Add the combined tag string to the meta array
                    $meta['tags'] = implode(', ', $tags);
                    // Add the meta array
                    $record[] = $meta;
                }
            }
            $i++;
        }
    
        return $record;
    }
    

        3
  •  0
  •   OverLex    15 年前

    如果我没说错的话:在桌子上 关于这些书的所有数据如下: 所以这样做:

    $this->db->select('*')->order_by('title');
    $query = $this->db->get('books');
    $result = $query->result();
    return $result;
    

    你应该返回你的书的所有数据,你不需要再次循环获得数据。

        4
  •  0
  •   Quasipickle    15 年前

    我对CodeIgniter一点都不熟悉,但我认为有一些通用的实践可以合并。

    • 如果这是一个浏览页面-没有分页吗?对结果进行分页可以大大减少每次页面加载时必须运行的查询数。
    • 有一个功能(比如, get_books_info() )您调用它来检索您的系统返回的所有书籍的所有标记和元信息 get_books() get_book_info() . 你甚至可以触发 -所以你只需要在需要数据的时候做这项工作。我觉得有点懒。
        5
  •  0
  •   Erwin    12 年前
    function get_book_info() {
    
        /*
         * SELECT b.isbn, b.title, b.publisher, b.date, b.thumb, b.filename, b.pages, t.tag
         * FROM books AS b
         * INNER JOIN books_tags AS bt ON b.isbn = bt.book_id
         * INNER JOIN tags AS t ON bt.tag_id = t.id
         * ORDER BY b.title, t.tag
         */
    
        $this->db->select('b.isbn, b.title, b.publisher, b.date, b.thumb, b.filename, b.pages, t.tag');
        $this->db->from('books AS b');
        $this->db->join('books_tags AS bt', 'b.isbn = bt.book_id', 'inner');
        $this->db->join('tags AS t', 'bt.tag_id = t.id', 'inner');
        $this->db->order_by('b.title, t.tag');
        $query = $this->db->get();
        $result = $query->result();
    
        $counter = '';
        $record = $meta = $tags = array();
        $count = count($result);
        $i = 1;
    
        foreach ($result as $book) {
            // If this is not the last row
            if ($i < $count) {
                // If this is the first appearance of this book
                if ($counter != $book->isbn) {
                    // If the meta array already exists
                    if ($meta) {
                        // Add the combined tag string to the meta array
                        $meta['tags'] = implode(', ', $tags);
                        // Add the meta array
                        $record[] = $meta;
                        // Empty the tags array
                        $tags = array();
                    }
                    // Reset the counter
                    $counter = $book->isbn;
                    // Grab the book from Amazon
                    $amazon = $this->amazon->get_amazon_item($book->isbn);
                    // Collect the book information
                    $meta = array(
                        'isbn' => $book->isbn,
                        'title' => strip_slashes($book->title),
                        'publisher' => strip_slashes($book->publisher),
                        'date' => date('F j, Y', strtotime($book->date)),
                        'thumb' => $book->thumb,
                        'file' => $book->filename,
                        'pages' => $book->pages,
                        'rating' => $amazon->Items->Item->CustomerReviews->AverageRating,
                        'raters' => $amazon->Items->Item->CustomerReviews->TotalReviews
                    );
                    // Add the tag to the tags array
                    $tags[] = $book->tag;
                } else {
                    // All we need is the tag
                    $tags[] = $book->tag;
                }
            // If this is the last row
            } else {
                // If this is the first appearance of this book
                if ($counter != $book->isbn) {
                    // Grab the book from Amazon
                    $amazon = $this->amazon->get_amazon_item($book->isbn);
                    // Collect the book information
                    $meta = array(
                        'isbn' => $book->isbn,
                        'title' => strip_slashes($book->title),
                        'publisher' => strip_slashes($book->publisher),
                        'date' => date('F j, Y', strtotime($book->date)),
                        'thumb' => $book->thumb,
                        'file' => $book->filename,
                        'pages' => $book->pages,
                        'rating' => $amazon->Items->Item->CustomerReviews->AverageRating,
                        'raters' => $amazon->Items->Item->CustomerReviews->TotalReviews
                    );
                    // Add the tag to the tags array
                    $tags[] = $book->tag;
                    // Add the combined tag string to the meta array
                    $meta['tags'] = implode(', ', $tags);
                    // Add the meta array
                    $record[] = $meta;
                } else {
                    // All we need is the tag
                    $tags[] = $book->tag;
                    // Add the combined tag string to the meta array
                    $meta['tags'] = implode(', ', $tags);
                    // Add the meta array
                    $record[] = $meta;
                }
            }
            $i++;
        }
    
        return $record;
    }
    
    推荐文章