mysql 加入 ON 和 AND 到 laravel eloquent

Posted

技术标签:

【中文标题】mysql 加入 ON 和 AND 到 laravel eloquent【英文标题】:mysql join ON and AND to laravel eloquent 【发布时间】:2015-02-12 04:27:07 【问题描述】:

我已经能够使用以下原始 sql 获得我需要的查询结果:

select `person`.`id`, `full_name`, count(actions.user_id) as total
from `persons`
left join `actions`
on `actions`.`person_id` = `persons`.`id` 
and `actions`.`user_id` = $user
where `type` = 'mp' 
group by `persons`.`id`

但我还不能让它在 eloquent 中工作。

基于一些类似的答案,我尝试了->where()leftJoin() 中的函数,但是$user 尚未过滤每个人的操作的count。就目前而言:

$query = Person::leftJoin('actions', function($q) use ($user)
        
            $q->on('actions.person_id', 'persons.id')
                ->where('actions.user_id', $user);
        )
        ->groupBy('persons.id')
        ->where('type', 'foo')
        //->where('actions.user_id', '=', $user)
        ->get(['persons.id', 'full_name', DB::raw('count(actions.id) as total')]);

我至少在大致朝着正确的方向前进,对吧...?

如果相关,Persons.php 模型有两个 actions 关系:

public function actions()

    return $this->hasMany('Action');


public function actionsUser($id)

    return $this->hasMany('Action')->where('user_id', $id);

【问题讨论】:

您是否在Person.php 类中指定表名是persons?如果不是,Laravel 将尝试调用 Person 的复数形式,在本例中为 People 表。 啊,对不起 - 我用这里的名字来掩盖实际正在做的事情,我没有意识到 Laravel 这么聪明! 【参考方案1】:

所以,作为参考,我这样解决了:

$query = Person::leftJoin('actions', function($q) use ($user)
        
            $q->on('actions.person_id', '=', 'persons.id')
                ->where('actions.user_id', '=', "$user");
        )
        ->groupBy('persons.id')
        ->where('type', 'foo')
        ->get(['persons.id', 'full_name', DB::raw('count(actions.id) as total')]);

奇怪的是,leftJoin 中的 ->where() 子句需要变量的语音标记才能正确通过 sql 查询(同样,“2”似乎不起作用,而“2”起作用)。

【讨论】:

是的,您需要为JoinClause 上调用的onwhere 指定所有3 个参数。对于" - 如果您传递变量,则无需这样做。 如果$user 是具有__toString() 方法的对象,则可能是将其插入字符串(在像"$user" 这样的双引号中)正在执行隐式(字符串)转换,该转换返回2。不看 $user 的类型就很难知道。【参考方案2】:

我发现where 并不总是适用于leftJoin 子句

如果你以后遇到任何问题,我建议你使用这个:

    $query = Person::leftJoin('actions', function($q) use ($user)
    
        $q->on('actions.person_id', '=', 'persons.id')
            ->on('actions.user_id', '=', "$user");
    )
    ->groupBy('persons.id')
    ->where('type', 'foo')
    ->get(['persons.id', 'full_name', DB::raw('count(actions.id) as total')]);

希望对某人有所帮助。

【讨论】:

我自己也得出了这个结论。使用 ->where 将强制 Eloquent 进行值参数绑定(例如 actions.user_id = ?)查询,而使用 ->on 只是比较 SQL 列。【参考方案3】:

当 laravel eloquent 开始变得像这样复杂时

为了获得更大的灵活性和可读性,我将只使用普通的 sql 语句,然后对结果进行水合。

$sql = "
    SELECT `person`.`id`,
        `full_name`,
        count(actions.user_id) AS total
    FROM `persons`
    LEFT JOIN `actions`
        ON `actions`.`person_id` = `persons`.`id` 
        AND `actions`.`user_id` = $user
    WHERE `type` = 'mp' 
    GROUP by `persons`.`id`
";

$query = Person::hydrate(
    DB::select( $sql )
);

【讨论】:

以上是关于mysql 加入 ON 和 AND 到 laravel eloquent的主要内容,如果未能解决你的问题,请参考以下文章

MySQL问题记录--Can't connect to MySQL server on localhost (10061)解决方法

Mysql问题:Can't connect to MySQL server on localhost (10061)解决方法

Can't connect to MySQL server on 'localhost' (10038)

SQL:在 Where 子句之后加入

MySQL 常用命令

mysql常用命令大全