Laravel 使用 CASE 从子查询提供数据

问题描述 投票:0回答:1

我的任务是向报告(源自 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?

laravel eloquent
1个回答
0
投票

快速阅读 laravel-eloquent-case

 文档建议您应该使用其他方法。

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
表达式。

© www.soinside.com 2019 - 2024. All rights reserved.