SQL查询生成器-分组和排序(Laravel)

时间:2019-01-17 11:32:56

标签: mysql laravel group-by sql-order-by

我需要从我的一个表中获取一组结果以输出到图表。图表需要显示“本学年(2018年9月1日至2018年8月31日)每个月的关注数量”。

返回的结果应该类似于:

| month     | total |
|-----------|-------|
| September | 15    |
| October   | 23    |
| December  | 24    |
| January   | 438   |

当我尝试将月份组合在一起时,问题就来了;我得到的计数值不正确。

我当前拥有的查询是:-

    // Returns 2018-09-01 00:00:00
        $start = Carbon::createMidnightDate(Carbon::now()->subMonths(8)->year, 9, 1);
    // Gets current date
        $end = Carbon::now();

        $concerns = DB::table('concerns')
            ->select(DB::raw('MONTHNAME(created_at) as month, count(*) as total, created_at'))
            ->whereBetween('created_at', [$start, $end])
            ->groupBy('month')
            ->groupBy('created_at')
            ->orderBy('created_at', 'asc')
            ->get()->mapWithKeys(function ($item) {
                return [$item->month => $item->total];
          });

但是这使我返回:-

| month     | total |
|-----------|-------|
| September | 1     |
| October   | 1     |
| December  | 1     |
| January   | 1     |

由于created_at日期的分组,显然不会将所有单个值加在一起,但是由于MySQL only_full_group_by模式,排除它会阻止我对它进行排序。

任何建议将不胜感激!

1 个答案:

答案 0 :(得分:2)

我认为您不需要created_at中的SELECT来获得所需的结果。您应该可以将查询简化为:

$concerns = DB::table('concerns')
    ->select(DB::raw('MONTHNAME(created_at) as month, count(*) as total'))
    ->whereBetween('created_at', [$start, $end])
    ->groupBy('month')
    ->orderBy('created_at', 'asc')

请注意,这假设$start$end之间的间隔为12个月或更短。否则,您也需要按YEAR(created_at)分组。

如果您正在运行MySQL 8,或者已启用only_full_group_by,则需要花更多的精力才能获得有效的查询,以满足GROUP BY的要求。这应该起作用:

$concerns = DB::table('concerns')
    ->select(DB::raw('MONTHNAME(created_at) AS month, YEAR(created_at) AS year, count(*) as total'))
    ->whereBetween('created_at', [$start, $end])
    ->groupBy('year', 'month')
    ->orderBy('year', 'asc')
    ->orderByRaw("MONTH(STR_TO_DATE(CONCAT('1 ', month, ' ', year), '%e %M %y')) asc")

我已经针对dbfiddle

进行了该查询的演示