You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel Eloquent(PostgreSQL)中用查询构建器实现WHERE子句使用别名?

问题描述

我原本的Laravel查询代码如下:

Student::query()
    ->addSelect(['presentCount' =>
        Score::query()
            ->selectRaw('count(*)')
            ->whereColumn('student_id', '=', 'students.id')
            ->where('created_at', '>', getBeginningOfThisYear())
            ->where('presence', '=', 1)
    ])->where('presentCount', '>=', 5)->get()

对应的原生SQL为:

select "students".*, (select count(*) from "scores" where "student_id" = "students"."id" and "created_at" > ? and "presence" = ? and "scores"."deleted_at" is null) as "presentCount" from "students" where "presentCount" >= ? and "students"."deleted_at" is null

这里的问题是presentCount是查询结果的别名,无法直接在WHERE子句中使用。我知道可以将SQL改写为嵌套子查询的形式解决:

select * from (select "students".*, (select count(*) from "scores" where "student_id" = "students"."id" and "created_at" > ? and "presence" = ? and "scores"."deleted_at" is null) as "presentCount" from "students" ) as students where "students"."presentCount" >= ? and "students"."deleted_at" is null

请问如何不使用原生SQL,仅通过Laravel查询构建器实现上述改写后的查询?

解决方案

方法一:嵌套子查询(fromSub)

先构建包含presentCount字段的子查询,再将其作为外层查询的数据源,在外层对别名字段进行筛选:

// 构建子查询:包含学生基础信息和presentCount统计
$subQuery = Student::query()
    ->addSelect(['presentCount' =>
        Score::query()
            ->selectRaw('count(*)')
            ->whereColumn('student_id', '=', 'students.id')
            ->where('created_at', '>', getBeginningOfThisYear())
            ->where('presence', '=', 1)
    ]);

// 外层查询基于子查询结果过滤
$students = DB::query()
    ->fromSub($subQuery, 'students')
    ->where('presentCount', '>=', 5)
    ->whereNull('students.deleted_at')
    ->get();

这段代码完全通过Laravel查询构建器生成你需要的嵌套SQL,无需手写原生语句。

方法二:使用HAVING子句筛选

由于presentCount是计算生成的字段,也可以直接用HAVING子句替代WHERE来筛选,写法更简洁:

$students = Student::query()
    ->addSelect(['presentCount' =>
        Score::query()
            ->selectRaw('count(*)')
            ->whereColumn('student_id', '=', 'students.id')
            ->where('created_at', '>', getBeginningOfThisYear())
            ->where('presence', '=', 1)
    ])
    ->having('presentCount', '>=', 5)
    ->get();

Laravel支持对查询中定义的别名使用HAVING,这种写法会生成等价的筛选逻辑,同样能解决别名无法在WHERE中使用的问题。

内容的提问来源于stack exchange,提问作者osama Abdullah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:39:34