Laravel 按查询分组

Laravel group by query

我在 Laravel 中得到了这个查询:

return $this->hasMany(Facility::class)
            ->select("id", "port_id", "facility",
                DB::raw("(SELECT count('*') FROM port_facilities
                                    WHERE has_it = 1) as has_it_true"),
                DB::raw("(SELECT count('*') FROM port_facilities
                                    WHERE has_it = 0) as has_it_false"))
            ->groupBy('facility');

一个港口是否有某些设施才算数。我现在遇到的问题是 groupBy 不工作。它计算的是一切,而不是 grouping 的设施。知道我该如何解决这个问题吗?

您在这里混合了两个 Laravel 组件。 1 是使用 Eloquent 的关系定义,另一个是使用 QueryBuilder。

从查询开始,您的 'adapted' 查询应该是以下几行:

Facility::select("id", "port_id", "facility",
                DB::raw("(SELECT count('*') FROM port_facilities
                                    WHERE has_it = 1) as has_it_true"),
                DB::raw("(SELECT count('*') FROM port_facilities
                                    WHERE has_it = 0) as has_it_false"))
            ->groupBy('facility')->get();

如果你想建立关系,那么在你想要指定关系的模型中,你应该像文档中列出的那样做:

https://laravel.com/docs/5.7/eloquent-relationships#defining-relationships

一条建议:不要 count('*') 除非你真的需要(你可以计算单个列或几个列并提高一些性能),不要将 QueryBuilder 与 Eloquent 混合使用,除非你真的需要

这里需要使用条件聚合:

return $this->hasMany(Facility::class)
    ->select("facility",
        DB::raw("COUNT(CASE WHEN has_it = 1 THEN 1 END) AS has_it_true"),
        DB::raw("COUNT(CASE WHEN has_it = 0 THEN 1 END) AS has_it_false"))
    ->groupBy('facility');

这将对应于以下原始 MySQL 查询:

SELECT
    facility,
    COUNT(CASE WHEN has_it = 1 THEN 1 END) AS has_it_true,
    COUNT(CASE WHEN has_it = 0 THEN 1 END) AS has_it_false
FROM port_facilities
GROUP BY
    facility;

请注意,我没有在 SELECT 子句中包含 idport_id,因为 MySQL 可能不接受这些列。一般情况下,在做GROUP BY facility时,我们可能只会select facilityfacility.

以外的列的聚合