2012-11-15 79 views
1

現在我使用下面的代碼從某些類別買書:如何讓本本

$options['conditions']['Category.id'] = $category_id; 
$options['joins'] = array(
    array(
     'table' => 'books_categories', 
     'alias' => 'BookCategory', 
     'type' => 'inner', 
     'conditions' => array('Book.id = BookCategory.id_book'), 
    ), 
    array(
     'table' => 'categories', 
     'alias' => 'Category', 
     'type' => 'inner', 
     'conditions' => array('BookCategory.kat = Category.id'), 
    ), 
); 

$this->Book->find('all',$options); 

這只是發現從給定的CATEGORY_ID所有圖書。

所以有3個表格:categories,booksbooks_categories。 books_categories有兩個檔案:book_idcategory_id所以基本上它只是HABTM關係。問題是,一本書可能屬於很多類別,我想要例如查找所有5類書籍,但不包括5,6和7類書籍。我該如何做?

編輯--------------------------------------------- ----------------------------------

好吧,我想出了它應該如何看待純SQL - 條件應該是這樣的:

where 
    category_id = <given category> 
    and books.book_id not in 
(
select book_id from book_categories 
    where category_id in (<given set of cat>) 
) 
order by books.inserted 

這將讓所有的書從一個範疇,而是從一組其他類別的圖書除外。 現在我想強制Cake生成類似的SQL查詢。 我試過到目前爲止:

$options['conditions']['Category.id'] = $category_id;  
$options['conditions']['AND'][] = 'Book.id NOT IN (SELECT id_book FROM book_categories WHERE kat IN (133,134))'; 

$options['order'] = array('Book.inserted' => 'desc'); 
$options['joins'] = array(
      array(
       'table' => 'book_categories', 
       'alias' => 'BookCategory', 
       'type' => 'inner', 
       'conditions' => array('Book.id = BookCategory.id_book'), 
      ), 
      array(
       'table' => 'categories', 
       'alias' => 'Category', 
       'type' => 'inner', 
       'conditions' => array('BookCategory.kat = Category.id'), 
      ), 
     ); 

這會產生這個查詢(索裏 - 表名是有點不同):

SELECT `Book`.`id`, `Book`.`OK`, `Book`.`price`, `Book`.`link`, `Book`.`title`, 
`Book`.`author`, `Book`.`img`, `Book`.`inserted`, `Book`.`checked`, `Book`.`big_img`, `Book`.`lang`, `Book`.`asin`, `Book`.`description`, `Book`.`last_update`, `Book`.`review`, `Book`.`changed` 
FROM `amazon`.`linki` AS `Book` 
inner JOIN `amazon`.`cross_kategorie_full` AS `BookCategory` ON (`Book`.`id` = `BookCategory`.`id_book`) 
inner JOIN `amazon`.`kategorie` AS `Category` ON (`BookCategory`.`kat` = `Category`.`id`) 
WHERE `Category`.`id` = 4 
AND `Book`.`OK` = 'OK' 
AND ((`Book`.`big_img` NOT LIKE '%no-image%') 
AND (`Book`.`id` NOT IN (SELECT id_book FROM cross_kategorie_full WHERE kat IN (133,134)))) 
ORDER BY `Book`.`inserted` desc LIMIT 20 

但有錯誤:30秒最大的執行時間超過了 - 所以有是不結束在此SQL語句(循環?)什麼......

+0

你必須使用mysql命令來運行此查詢從殼。超時是因爲你通過php腳本運行它(我是否正確?)... – Oerd

+0

現在,這個查詢優化問題是另一個問題:)你知道你正在運行'NOT IN(SELECT id_book FROM。每個單獨的記錄都是?'(正如我微妙地提示我的答案)。這是另一個加入我的朋友! – Oerd

回答

0

更新相對於更新的問題
爲SQL以獲得正確的結果(在可接受的時間內),您需要再次使用Categories加入另一個別名。由於這導致了另一個問題,我建議你發佈它標記爲mysqlquery-optimization
結束時更新

正因爲如此,一個HABTM關係有點狡猾(因爲它確實不是一個HABTM)。如果您在books_categories中每次進行書籍類別匹配只有一行,則無法知道某本書屬於哪些其他類別,因此您無法確切知道您確實需要哪些類別(即不屬於其他類別)。它是CakePHP的數據層和模型,可以在幕後爲你解決這個問題:)

我看到的唯一解決方案是使用Set::extract來進一步查詢你得到的結果並過濾出屬於你沒有的類別的書籍,不想包含。 (類似:

// returns all books not belonging to categories 3,4 
$new_result = Set::extract('/Books/Category[id!=3][!=4]', $results); 

在一個側面說明,我發現它非常有用在這樣的情況下,查詢數據庫和可視化的SQL查詢得到你所需要的結果的複雜性也,你應該激活CakePHP調試工具欄來查看發送到數據庫的SQL查詢,以便您更好地瞭解幕後發生的事情。

CakePHP書籍,在"Associations: Linking models together"末尾建議以下內容: 。

Using joins allows you to have a maximum flexibility in how CakePHP handles associations and fetch the data, however in most cases you can use other tools to achieve the same results such as correctly defining associations, binding models on the fly and using the Containable behavior. This feature should be used with care because it could lead, in a few cases, into bad formed SQL queries if combined with any of the former techniques described for associating models.

+0

但是,如果我想分頁結果,我會得到例如20本書 - 然後我使用Set :: extract(。 ..)'',我有不到20本書 - 我怎麼能克服這個? – user606521

+0

拉一些更多的數據庫(說,另一個20)提取你所需要的,與以前的設置合併,限制到20. This isn' t「智能」解決方案,但你需要做的也不是標準的。 OTOH你也可以直接在db上執行查詢。 – Oerd

+0

我更新了我的問題 - 現在我知道如何在SQ中完成L但我必須在CAKE中完成。 – user606521

0

我認爲那裏有一個錯字。你想從第5類獲得所有書籍,但不能從第5,6和7類獲得書籍?

沒關係。 Cake的傳言指出,在HABTM表中應該總是有一個主鍵,所以你可以添加一個「id」列。有了這個,接下來的步驟要容易得多,或者我應該說:「他們正在變得可能」。

接下來你要做的是創建一個名爲「BooksCategory」的關聯模型。 使用此處解釋的'with'索引將您的圖書和類別模型與新模型相互關聯。如果鏈接模型屬於插件,請不要忘記使用插件語法(PluginName.ModelName)。 您現在正在鏈接模型中爲您鏈接的每個模型放置兩個belongsTo關聯。這確保在找到時抓取這些人。

你做的下一件事是:

$this->Book->BooksCategory->find(
    'all', 
    array(
     'conditions' => array(
      'BooksCategory.category_id' => 5 
     ) 
    ) 
); 

完成;)不,你只得到從類圖書5

問候 func0der

+0

這不是問題。讓我們說書屬於1,2和3類。我希望所有書籍從類別1,但不是從類別2和3.書籍可能有很多類別... – user606521

+0

你想要只在類別1,但不是!在貓2或3? – func0der

+0

是的 - 無論如何,我的更新代碼中的解決方案工作正常,但只有在集合中的元素數量爲1的情況下。我有兩個或更多的元素,它的工作極其緩慢...像15秒查詢 – user606521