Получить различия для каждого значения из двух строк

Итак, у меня есть этот запрос, который группирует company, и нахожу последние две строки из периодов для каждой компании из salesreport

App\salesreport::join(DB::RAW('(SELECT company_id, GROUP_CONCAT(periods ORDER BY periods DESC) grouped_periods FROM salesreport GROUP BY company_id ) latest_report'),function($join){
        $join->on('salesreport.company_id','=','latest_report.company_id');
        $join->whereBetween(DB::raw('FIND_IN_SET(`salesreport`.`periods`, `latest_report`.`grouped_periods`)'), [1, 2]);
    })->get();

и его возвращаемая таблица, которая выглядит так

+----+------------+-------+------------+
| id | company_id | value |  periods   |
+----+------------+-------+------------+
|  1 | A1         |   100 | 2017-02-02 |  
|  2 | A1         |   150 | 2017-01-01 |  
|  3 | A2         |    80 | 2017-06-01 |  
|  4 | A2         |    60 | 2017-04-01 | 
+----+------------+-------+------------+

и на следующем шаге я хочу найти различия для каждого значения (которое в этом простом примере является только столбцом значений, но реальный проект содержит много столбцов

чтобы это было что-то вроде этой таблицы

+----+------------+-----------+------------+
| id | company_id |   value   |  periods   |
+----+------------+-----------+------------+
|  1 | A1         | 100 (-50) | 2017-02-02 |
|  3 | A2         | 80 (+20)  | 2017-06-01 |
+----+------------+-----------+------------+

как это сделать? возможно ли это в одном запросе к базе данных? поскольку я думаю, что у нас уже есть данные под рукой, но нам нужно найти элегантный способ сделать расчет между первой и второй строками для каждой группы компаний в отчете о продажах и превратить их в некоторые новые поля

так что может быть что-то вроде

App\salesreport::join(DB::RAW('(SELECT company_id, GROUP_CONCAT(periods ORDER BY periods DESC) grouped_periods FROM salesreport GROUP BY company_id ) latest_report'),function($join){
        $join->on('salesreport.company_id','=','latest_report.company_id');
        $join->whereBetween(DB::raw('FIND_IN_SET(`salesreport`.`periods`, `latest_report`.`grouped_periods`)'), [1, 2]);
    })->addSelect([DB::raw('(row1.value - row2.value) as row_differences')])->get();
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
0
61
1

Ответы 1

Возможно (но, вероятно, не лучшая идея):

App\salesreport::join(DB::RAW('(SELECT company_id, MAX(periods) AS max_periods FROM salesreport GROUP BY company_id ) latest_report'),function($join){
    $join->on('salesreport.company_id','=','latest_report.company_id');
    $join->on('salesreport.periods','=','latest_report.max_periods');
})->select('*')->selectRaw(
    'CAST(`value` AS SIGNED)-CAST((
        SELECT `value`
        FROM `salesreport`
        WHERE `company_id`=`latest_report`.`company_id`
        ORDER BY `periods` DESC
        LIMIT 1,1
    ) AS SIGNED) as `difference`'
)->get();

Если столбец value - это SIGNED, отливку можно удалить.

хммм странно, я только что понял, что разница не совпадает с ручным расчетом, я пытался вычислить вручную значение в первом и втором периодах и получил неправильное число

PamanBeruang 25.03.2018 07:55

Работает ли он с данными примера из вашего вопроса?

Jonas Staudenmeir 25.03.2018 16:47

Какой результат вы получите?

Jonas Staudenmeir 25.03.2018 17:19

Другие вопросы по теме