1 回答
TA贡献1871条经验 获得超8个赞
事实上,两者都不正确。正确的说法是:
“检索所有没有评论的帖子,或者所有评论都来自被禁止的作者”
我为 Laravel 文档创建了这个拉取请求来更正措辞。
从这样的调用生成的 sql 将如下所示:
SELECT
*
FROM
`posts`
WHERE
NOT EXISTS( SELECT
*
FROM
`comments`
WHERE
`posts`.`id` = `comments`.`postId`
AND EXISTS( SELECT
*
FROM
`authors`
WHERE
`comments`.`authorId` = `authors`.`id`
AND `banned` = 0))
细分一下,内部查询说“找到与每个帖子相关的所有评论,其中该评论是由未被禁止的作者撰写的。
SELECT
*
FROM
`comments`
WHERE
`posts`.`id` = `comments`.`postId`
AND EXISTS( SELECT
*
FROM
`authors`
WHERE
`comments`.`authorId` = `authors`.`id`
AND `banned` = 0)
然后,顶级查询说:“现在,给我上面子查询没有返回行的所有帖子”
即,所有作者都被禁止,或者根本没有评论。
SELECT
*
FROM
`posts`
WHERE
NOT EXISTS(
{.. sub query above here }
)
如果你想自己测试一下,
楷模:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Post extends Model
{
public function comments(): HasMany
{
return $this->hasMany(Comment::class, 'postId');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Comment extends Model
{
public function author(): HasOne
{
return $this->hasOne(Author::class, 'id', 'authorId');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Author extends Model
{
}
创建表Sql:
CREATE TABLE `posts` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE `comments` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`postId` BIGINT(20) NOT NULL,
`authorId` BIGINT(20) NOT NULL,
`content` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `authors` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
);
内容sql:
# crate a post
INSERT INTO `posts` (`id`) VALUES ('1');
# add a banned and not banned author
INSERT INTO `authors` (`name`, `banned`) VALUES ('Jack', '0');
INSERT INTO `authors` (`name`, `banned`) VALUES ('Jill', '1');
# add a comment from a banned and not banned author
INSERT INTO `comments` (`postId`, `authorId`, `content`) VALUES ('1', '1', 'a');
INSERT INTO `comments` (`postId`, `authorId`, `content`) VALUES ('1', '2', 'b');
现在运行代码:
$post = \App\Models\Post::whereDoesntHave('comments.author', function ( $query) {
$query->where('banned', 0);
})->get();
您将得到 0 个结果。
现在运行此命令以使两位作者都不会被禁止:
UPDATE `authors` SET `banned`='0';
您仍然会得到 0 个结果。
现在运行这个命令来禁止两位作者:
UPDATE `authors` SET `banned`='1';
您现在将返回 1 个结果。
现在运行此命令,使两位作者不再被禁止,但删除他们的评论:
UPDATE `authors` SET `banned`='0';
DELETE FROM `comments`;
您现在将返回 1 个结果。
这证明实际行为是“检索所有没有评论的帖子,或者所有评论都来自被禁止的作者”
- 1 回答
- 0 关注
- 139 浏览
添加回答
举报