【问题标题】:Laravel group by queryLaravel 按查询分组
【发布时间】:2018-10-15 08:54:03
【问题描述】:

我在 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。知道如何解决这个问题吗?

【问题讨论】:

    标签: mysql laravel query-builder


    【解决方案1】:

    这里需要使用条件聚合:

    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时,我们可能只选择facilityfacility以外的列的聚合。

    【讨论】:

      【解决方案2】:

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

      从查询开始,您的“适应”查询应该是以下几行:

      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 混合使用

      【讨论】:

      • 这可以工作,但您需要将这些子查询与外部查询相关联,例如使用(SELECT COUNT(*) FROM port_facilities pf2 WHERE pf1.facility = pf2.facility AND pf2.has_it = 1)
      • 是的,我想我更关注它的结构而不是它为什么不起作用,你的答案是正确的:P
      猜你喜欢
      • 2017-04-22
      • 2015-01-01
      • 1970-01-01
      • 2015-06-27
      • 1970-01-01
      • 2020-06-04
      • 2021-11-24
      • 2014-08-27
      相关资源
      最近更新 更多