首页 > 解决方案 > Laravel 选择列,然后按日期对列值进行分组

问题描述

我试图让看起来像一个简单的 SQL 查询的东西在我的 Laravel 项目中工作,我有一个前端 Web 应用程序,允许用户从各种预定义的表和可选择的列列表中提取数据.

如果我不尝试selectgroupBy在一起,这很好用,同样,我需要根据用户是否希望按天或一个月对数据进行分组来进行分组。

我的 POST 请求看起来像,其中父数组中的每个数组项都是一个表:

[
  [
    table: 'my_table',
    columns: ['event_category', 'event_action', 'event_count', 'created_at'] ...
    filterBy: [
      ['event_category', 'my category'],
      ['event_action', 'some action']
    ],
    orderBy: {
      field: 'created_at',
      direction: 'desc'
    }
  ]
]

中的每一行都my_table包含一event_count列,其中包含一个数字,因此如果特定日期有 5 行具有不同的event_count数字,我需要将所有这些event_count条目相加并按当天分组

这是我的功能和查询:

public function findDataFromSources(Request $request)
{

    $request_data = $request->all();
    $realData = [
      'size' => 0,
      'results' => [],
      'filtered' => []
    ];

    foreach ($request_data as $key => $findable) {
      // NOTE: this works for retrieving data that isn't grouped
      // $res = DB::table($findable['table'])
      //          ->select($findable['columns'])
      //          ->where($findable['filterBy'])
      //          ->orderBy($findable['orderBy']['field'], $findable['orderBy']['direction'])
      //          ->take(20)
      //          ->get();

      // TODO: this isn't grouping for some reason...
      $res = DB::table($findable['table'])
              ->select($findable['columns'], DB::raw('sum(event_count) as total_events'))
              ->groupBy('created_at')
              ->orderBy($findable['orderBy']['field'], $findable['orderBy']['direction'])
              ->get();

      $realData['size'] += count($res);
      array_push($realData['results'], $res);
    }

    $data = [
      'success' => true,
      'message' => 'Your chosen data sources and fields',
      'sources' => $realData
    ];

}

我错过了什么?我得到的错误是:

SQLSTATE [42000]:语法错误或访问冲突:1055 SELECT 列表的表达式 #1 不在 GROUP BY 子句中并且包含非聚合列

标签: phpsqllaravellaravel-query-builder

解决方案


->select($findable['columns']

您不能在没有聚合函数的情况下不在SELECT其中的字段/列,并且您可能包含不在.GROUP BY$findable['columns']GROUP BY

例如,您可以使用ANY_VALUE()@RobbinBenard 评论

->select(DB::raw('ANY_VALUE(' .$findable['columns'][0] .')'))

您可以遍历列并使用它addSelect()来添加这些列。

  $query = DB::table($findable['table'])
          ->select(DB::raw('sum(event_count) as total_events'));

  foreach($findable['columns'] as $column) {
          $query->addSelect(DB::raw('ANY_VALUE(' .$column .')'));
  }

  $res = $query->groupBy('created_at')
         ->orderBy($findable['orderBy']['field'], $findable['orderBy']['direction'])
         ->get();

推荐阅读