我的任务是向报告(源自 MySQL 数据库)添加一个新的特定列,其条件是根据条件返回新列值。这似乎是 CASE 子句的理想用途:
select *,
CASE
WHEN check_out_time >= now() + INTERVAL 25 HOUR THEN "Requires Attention"
WHEN (
SELECT count(*)
FROM shift_activities
WHERE shift_id = `shifts`.`id`
) <= 0 THEN "Requires Attention"
ELSE "Complete"
END AS "VisitStatus"
from `shifts`
-- JOINs left off
唯一的缺点是,这些 CASE/WHEN 子句之一需要子查询,这不太适合 Eloquent。这种情况下,Eloquent 查询就比较简单了:
$open_shifts = $client->shifts()
->with("customers", "activities")
->get();
使用 laravel-eloquent-case 扩展,可以直接添加一个 CASE,进行简单的比较:
$open_shifts = $client->shifts()
->with('caregiver', 'activities')
->case(function (CaseBuilder $case) {
$case->when('checked_out_time', '>=', 'INTERVAL 25 HOUR')->then('Requires Attention')
->else('Complete');
}, 'VisitStatus')
->get();
但是由于我有一个依赖于连接表的计数(*)的表,所以它的工作效果不太好。它会导致持续的错误,我不清楚如何在这里最好地使用该库。在 Eloquent 中使用此 CASE/WHEN 还需要哪些其他选项,或者我应该在这里使用原始 SQL?
INTERVAL 25 HOUR
是一个 SQL 表达式,因此可能应该使用 whenRaw
。
对于子查询,我认为你可以使用
DB
Facade 的 toSql/toRawSql
方法来获得正确的表达式。
->case(
function (CaseBuilder $case) {
$sub = DB::query()
->selectRaw('count(*)')
->from('shift_activities')
->whereColumn('shift_id', 'shifts.id');
$case
->whenRaw('checked_out_time >= INTERVAL 25 HOUR')->then('Requires Attention')
->whenRaw("({$sub->toSql()}) <= 0", $sub->getBindings())->then('Requires Attention') // although $sub->getBindings() could be ommited here since there are no bindings.
->else('Complete');
},
'VisitStatus'
)
就我个人而言,我总是使用原始语句来表示
CASE WHEN
表达式。