orderBy 可以按照关联 with 查询里面的字段排序吗?

orderBy 可以按照with 查询里面的字段排序吗? orderBy 如何加子查询喃?

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 12

上面说的不对,orderBy可以根据with关联中的字段来进行排序的,排序的实现是以子查询的方式来的;数据量一大就会比较慢,不建议这么使用;如果不考虑性能,写法真的非常方便简洁;

直接贴代码,首先注册Illuminate\Database\Eloquent\Builder

Builder::macro('orderByWith', function ($relation, $column, $direction = 'asc'){
    /** @var Builder $this */
    if (is_string($relation)) {
        $relation = $this->getRelationWithoutConstraints($relation);
    }

    return $this->orderBy(
        $relation->getRelationExistenceQuery(
            $relation->getRelated()->newQueryWithoutRelationships(),
            $this,
            $column
        ),
        $direction
   );
});

然后就可以直接使用了

// 查询用户列表,根据订单关联的价格字段进行倒排
User::where(...)->orderByWith('orders','price','desc')->get();

PS:laravel7+以上使用, 低版本没有试过

1年前 评论
tiantian10000 (楼主) 1年前
还不出来 (作者) 1年前

不可以,那是个子查询

1年前 评论
tiantian10000 (楼主) 1年前
tiantian10000 (楼主) 1年前

orderBy 后面跟子查询是什么意思, orderBy都是在最后执行的了呀

1年前 评论

with 实际上是执行了两条 sql ,第一条 sql 执行完之后,根据第一次查询出的结果,通过 IN 获取 with 内关联的表数据

User::with('article')->where('id', '>', 10)->orderByDesc('id')->get();
// 实际执行两条 sql
// SELECT * FROM user WHERE id > 10 ORDER BY id DESC;
// SELECT * FROM article WHERE user_id IN(13,12,11); -- 这里的 user_id 是模型指定的关联字段,in内的字段为上一条 sql 查出的内容

综上所述,orderBy 是在执行 with 操作之前,故不能使用

1年前 评论
tiantian10000 (楼主) 1年前
荒街! (作者) 1年前

试试查出来后通过each循环,把需要排序的放到第一层,然后用sortBy()

1年前 评论

上面说的不对,orderBy可以根据with关联中的字段来进行排序的,排序的实现是以子查询的方式来的;数据量一大就会比较慢,不建议这么使用;如果不考虑性能,写法真的非常方便简洁;

直接贴代码,首先注册Illuminate\Database\Eloquent\Builder

Builder::macro('orderByWith', function ($relation, $column, $direction = 'asc'){
    /** @var Builder $this */
    if (is_string($relation)) {
        $relation = $this->getRelationWithoutConstraints($relation);
    }

    return $this->orderBy(
        $relation->getRelationExistenceQuery(
            $relation->getRelated()->newQueryWithoutRelationships(),
            $this,
            $column
        ),
        $direction
   );
});

然后就可以直接使用了

// 查询用户列表,根据订单关联的价格字段进行倒排
User::where(...)->orderByWith('orders','price','desc')->get();

PS:laravel7+以上使用, 低版本没有试过

1年前 评论
tiantian10000 (楼主) 1年前
还不出来 (作者) 1年前

巧了,我最近刚好也有同样的需求,然后在stackoverflow上找了到一个方法,亲测有效

// 两张表,一张 elevators 一张 elevators_extras
// elevators_extras.elevator_id和elevators.id关联
// 检索elevators根据elevator_extras.is_urgent排序

$listData = Elevator::with(['extra'])
->orderBy(ElevatorExtra::select('is_urgent')->whereColumn('elevator_extras.elevator_id', 'elevators.id'), 'desc')
->paginate($form['pageSize']);
1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!