SQL Query Builder - группировка и упорядочение (Laravel) - PullRequest
0 голосов
/ 17 января 2019

Мне нужно получить набор результатов из одной из моих таблиц для вывода на график. На диаграмме должно быть указано «количество проблем за каждый месяц этого учебного года (с 1 сентября 2018 года по 31 августа 2018 года)».

Возвращенный результат должен выглядеть примерно так:

| 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 голосов
/ 17 января 2019

Я не думаю, что вам нужно 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

...