Cakephp 如何从一个类别(不包括其他类别)获取书籍(通过交叉表)

Cakephp 如何从一个类别(不包括其他类别)获取书籍(通过交叉表),cakephp,cakephp-2.1,Cakephp,Cakephp 2.1,目前,我使用以下代码从特定类别获取书籍: $options['conditions']['Category.id'] = $category_id; $options['joins'] = array( array( 'table' => 'books_categories', 'alias' => 'BookCategory', 'type' => 'inner', 'conditions' =>

目前,我使用以下代码从特定类别获取书籍:

$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);
这只是查找给定类别id中的所有书籍

因此有三个表:
类别
书籍
书籍_类别
。图书分类有两个文件:
book\u id
category\u id
,因此基本上它只是一个关系。问题是一本书可能属于多个类别,例如,我想查找类别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
这将生成此查询(sory-表名称略有不同):

但是有一个错误:超过了30秒的最长执行时间-所以在这个sql语句中有一些东西没有结束(循环?)。

相对于更新的问题更新
为了让sql产生正确的结果(在可接受的时间内),您需要使用
类别
再次为其提供另一个别名。由于这引出了另一个问题,我建议您将其贴上标签,标签为
mysql
queryoptimization

结束更新

事实上,HABTM关系有点曲折(因为它实际上不是HABTM)。如果在
books\u categories
中,每个图书类别只有一行匹配,则无法知道某本书属于哪些其他类别,因此无法真正确定您真正想要的类别(即不属于那些其他类别)。CakePHP的数据层和模型在幕后为您解决了这个问题:)

我看到的唯一解决方案是使用它来进一步查询您得到的结果,并过滤掉属于您不想包含的类别的书籍。(例如:

// returns all books not belonging to categories 3,4
$new_result = Set::extract('/Books/Category[id!=3][!=4]', $results); 
另一方面,我发现在类似这样的情况下,查询数据库并可视化SQL查询的复杂性非常有用,可以获得所需的结果。此外,您应该激活CakePHP调试工具栏,查看发送到数据库的SQL查询,以便更好地了解幕后的情况

CakePHP书在本节末尾提出了以下建议(强调我的观点)

使用联接允许您在CakePHP如何处理关联和获取数据方面具有最大的灵活性,但是在大多数情况下,您可以使用其他工具来实现相同的结果,例如正确定义关联、动态绑定模型和使用可包含行为。应谨慎使用此功能,因为它可能导致,在某些情况下,如果与前面描述的用于关联模型的任何技术相结合,则会生成格式错误的SQL查询

相对于更新的问题进行更新
为了让sql产生正确的结果(在可接受的时间内),您需要再次加入
类别
,给它另一个别名。因为这会引出另一个问题,我建议您将其贴上带有
mysql
查询优化的标签
结束更新

事实上,HABTM关系有点曲折(因为它实际上不是一个HABTM)。如果在
books\u categories
中,每个图书类别只有一行匹配,那么你无法知道某本书属于哪些其他类别,因此你无法真正说出你真正想要的(即不属于那些其他类别)。是CakePHP的数据层和模型在幕后为您解决了这个问题:)

我看到的唯一解决方案是使用它来进一步查询您得到的结果,并过滤掉属于您不想包含的类别的书籍。(例如:

// returns all books not belonging to categories 3,4
$new_result = Set::extract('/Books/Category[id!=3][!=4]', $results); 
另一方面,我发现在类似这样的情况下,查询数据库并可视化SQL查询的复杂性非常有用,可以获得所需的结果。此外,您应该激活CakePHP调试工具栏,查看发送到数据库的SQL查询,以便更好地了解幕后的情况

CakePHP书在本节末尾提出了以下建议(强调我的观点)

使用联接允许您在CakePHP如何处理关联和获取数据方面具有最大的灵活性,但是在大多数情况下,您可以使用其他工具来实现相同的结果,例如正确定义关联、动态绑定模型和使用可包含行为。应谨慎使用此功能,因为它可能导致,在某些情况下,如果与前面描述的用于关联模型的任何技术相结合,则会生成格式错误的SQL查询


我想这里面有一个打字错误。你想把所有的书都从第五类中拿出来,而不是从第五类、第六类和第七类中拿出来

Nevermind.Cake惯例指出,HABTM表中应该始终有一个主键,因此您可以添加一个“id”列。这样,接下来的步骤就容易多了,或者我应该说:“它们正在变得可能”

接下来要做的是,创建一个名为“BooksCategory”的关联模型。 使用此处介绍的“with”索引将您的书籍和类别模型通过新模型相互链接。如果链接模型属于插件,请不要忘记使用插件语法(PluginName.ModelName)。 现在,您正在链接的每个模型的链接模型中放置两个belongsTo关联。这确保在查找时获取这些关联

接下来要做的是:

$this->Book->BooksCategory->find(
    'all',
    array(
        'conditions' => array(
            'BooksCategory.category_id' => 5
        )
    )
);
不,你只能得到第五类的书

问候
func0der

我想里面有个打字错误。您想从类别5中获取所有书籍,但不想从类别5、6和7中获取

别客气。Cake惯例指出,HABTM表中应该始终有一个主键,因此可以添加一个“id”列。有了这一点,接下来的步骤就容易多了,或者我应该说:“他们越来越有可能了。”
$this->Book->BooksCategory->find(
    'all',
    array(
        'conditions' => array(
            'BooksCategory.category_id' => 5
        )
    )
);