php - 查找已标记为 X 和 Y 但未标记为 Z 的文章
问题描述
假设我的文章可以有很多标签。我希望能够找到所有标记为 X 和 Y,但不是 Z 的文章。
数据库看起来像这样:
文章
- ID
- 标题
- 身体
标签
- ID
- 姓名
文章标签
- article_id
- tag_id
现在,如果我想找到所有标记为 X 和 Y 的文章,我可以这样做:
$tags = ['X', 'Y'];
$articles = TableRegistry::get('Articles');
$articles = $articles
->find()
->innerJoinWith('Tags')
->where(['Tags.name IN' => $tags])
->group(['Articles.id'])
->having([$this->query()->newExpr('COUNT(DISTINCT Tags.name) = ' . count($tags))]);
或者如果我想找到所有没有被标记为 Z 的文章,我可以这样做:
// ...
$articles = $articles
->find()
->notMatching('Tags', function ($q) use ($tags) {
return $q->where(['Tags.name IN' => $tags]);
});
但是,如果我想查找所有标记为 X 和 Y 而不是 Z 的文章怎么办?我花了几个小时试图获得一个有效的查询,但我就是想不通。
如果我结合这两个查询,我会收到以下错误:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Tags.name' in 'where clause'
组合查询如下所示:
$tags = ['X', 'Y'];
$tags_not = ['Z'];
$articles = TableRegistry::get('Articles');
$articles = $articles
->find()
->innerJoinWith('Tags')
->where(['Tags.name IN' => $tags])
->group(['Articles.id'])
->having([$this->query()->newExpr('COUNT(DISTINCT Tags.name) = ' . count($tags))])
->notMatching('Tags', function ($q) use ($tags_not) {
return $q->where(['Tags.name IN' => $tags_not]);
});
有任何想法吗?
解决方案
$excluded = $this->Articles
->find()
->select('id')
->matching('Tags', function($q) use($tags_not) {
return $q->where(['Tags.name IN' => $tags_not]);
})->toArray();
$excludedIds = array_column($excluded, 'id');
$articles = $this->Articles
->find()
->where(['Articles.id NOT IN' => $excludedIds])
->matching('Tags', function($q) use($tags) {
return $q->where(['Tags.name IN' => $tags]);
});
推荐阅读
- powershell - 转换证书时 PowerShell 中的 Openssl 错误
- c - i686-elf-gcc 生成 64 位文件而不是 32 位文件?
- typescript - Roblox 机器人推广系统
- postgresql - psql 不显示关系、表。示例“选择 2+2;” 什么都不返回
- html - 在 Angular 中为图像源使用动态名称
- c++ - 如何在其他函数中声明函数?
- java - 从文件中读取一个随机单词供用户猜测 - Java
- c# - MVC5 ADFS 未经过身份验证
- dialogflow-es - 允许使用电话网关对 Dialogflow 进行长时间的用户响应?
- java - 尝试从远程 SSL 地址下载和设置证书以进行 WebSocket 连接,但出现“签名不匹配”异常