我有表名称应用程序和状态。表格如下:
表:应用:
id | 状态_id | is_active |
---|---|---|
1 | 1 | 真实 |
2 | 1 | 真实 |
3 | 1 | 真实 |
4 | 2 | 真实 |
5 | 2 | 真实 |
表:状态:
id | 描述 |
---|---|
1 | 已完成 |
2 | 待定 |
3 | 已处理 |
4 | 失败了 |
我正在尝试根据状态对申请进行计数。我想要刀片的预期输出:
状态 | 总计 |
---|---|
全部 | 5 |
已完成 | 3 |
待定 | 2 |
已处理 | 0 |
失败 | 0 |
我在控制器中使用 eloquent 来获取计数,但我必须为每个状态创建不同的变量。
$total = Application::select('*')
->where('is_active', 'true')
->count();
$complete = Application::select('*')
->where('application_sts', 1)
->where('is_active', 'true')
->count();
有什么简单的方法可以做到这一点吗?
你可以这样做:
Status::select(DB::raw('status.id, status.desc, COUNT(*) AS count'))
->join('applications', 'status.id', '=', 'applications.status_id')
->groupBy('status.id')->get();
或者这样:
DB::table('applications')->select(DB::raw('status.id, status.desc, COUNT(*) AS count'))
->join('status', 'status.id', '=', 'applications.status_id')
->groupBy('status.id')->get();
您可以有一个基本查询,然后仅应用正在更改的内容,这样您就不会每次都重复相同的代码:
$query = Application::select('*')
->where('is_active', 'true');
$total = $query->clone()->count();
$complete = $query->clone()->where('application_sts', 1)->count();
请注意,您必须克隆
$query
,因为这不是一个不可变的对象
applications
表必须左连接到 status
表,以确保所有雕像都得到代表(即使 applications
表中没有合格记录)。换句话说,join()
或 innerJoin()
将无法正常工作。
在
WITH ROLLUP
语句中使用 groupBy()
可在结果集中包含总计行。在 selectRaw()
调用中, COALESCE()
将 NULL
desc
值设置为 total
,因为 ROLLUP 功能不允许直接别名。 ROLLUP
一种数据库方言的语法可能与另一种数据库方言不同;我的脚本是为 MySQL 编写的。
当您需要在 SQL 中执行条件计数时,请使用
SUM()
并在内部进行比较,而不是使用 COUNT()
,后者需要更详细的 CASE
语句。
构造所需数据的最紧凑方法是构建关联数组。使用
pluck()
和两个参数来定义值和键。
如果标签的第一个字母需要转换为大写,可以使用 PHP 的
ucfirst()
(甚至使用 CSS)在视图/刀片中执行简单的格式化任务。
作为警告,我想说使用关键字和保留字作为表或列名是一个糟糕的选择,在构建查询时需要特殊处理/转义。最好完全避免这些命名冲突。
代码:(PHPize演示)
var_export(
DB::table('status')
->selectRaw("COALESCE(`desc`, 'total') `desc`, COALESCE(SUM(is_active = 'true'),0) count")
->leftJoin('applications', 'status.id', '=', 'applications.status_id')
->groupByRaw('`desc` WITH ROLLUP')
->orderBy('count', 'DESC')
->get()
->pluck('count', 'desc')
->toArray()
);
输出:
array (
'total' => '5',
'completed' => '3',
'pending' => '2',
'failed' => '0',
'processed' => '0',
)