Как написать запрос, чтобы получить сумму последних n элементов каждой строки? - PullRequest
1 голос
/ 15 апреля 2019

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

Это то, что яИмеем, скажем, N равно 2, и у меня есть эти данные,

day shop  sales
1    A    10
2    A    20  
3    A    30
4    A    40
5    A    50
1    B    100
2    B    200
3    B    300
4    B    400
5    B    500

Я хочу следующий результат

day | shop | total sales of last 2 days
1     A       10
2     A       30 //sum of 10 and 20   
3     A       50 // sum of 20 and 30 
4     A       70  //sum of 30 and 40
5     A       90 // sum of 40 and 50
1     B       100
2     B       300
3     B       500
4     B       700
5     B       900

Возможно ли сделать это в одном запросе?

Ответы [ 2 ]

2 голосов
/ 15 апреля 2019

В MySQL 8+ просто используйте lag():

select t.*,
       (t.sales + lag(t.sales, 1, 0) over (partition by t.shop order by t.day)
       ) as two_day_sales
from t;

В старых версиях используйте left join:

select t.*,
       (t.sales + coalesce(tprev.sales, 0)) as two_day_sales
from t left join
     t tprev
     on tprev.shop = t.shop and
        tprev.day = t.day - 1;
0 голосов
/ 15 апреля 2019

Могу я предложить следующую идею:

  • Получить все sales, упорядоченные по shop ASC, day ASC.
  • Затем на вашем внутреннем языке (я использую PHP),напишите код, который получает в массиве sales в соответствии с numberOfDays.

Вот полный пример в PHP, но вы можете использовать любой язык, который идет с MySQL, как вам нравится:

$connection = mysqli_connect("localhost", "root", "", "database_test");

$sql_query = "
                SELECT *
                FROM table_sales
                ORDER BY shop ASC, day ASC
             ";

$result = mysqli_query($connection, $sql_query);

$numberOfDays = 3;
$daily_sales = array();
$total_sales = array();
$i = 0;

while($row = mysqli_fetch_array($result)) {

    $daily_sales[$i] = $row;
    $total_sales[$i] = $row;
    $total_sales[$i]["sales"] = 0;

    $offset = $i - $numberOfDays + 1;

    if($offset < 0)
        $offset = 0;

    for($j = $offset; $j <= $i; $j++) {
        if($total_sales[$i]["shop"] == $daily_sales[$j]["shop"])
            $total_sales[$i]["sales"] += $daily_sales[$j]["sales"];
    }

    $i++;
}

mysqli_close($connection);

$total_sales - это многомерный массив.Вы можете получить к нему доступ, например, так: $total_sales[0]["sales"], и он даст вам общую сумму продаж за numberOfDays для конкретного магазина, который вы можете увидеть в $total_sales[0]["shop"].

Не забудьте сделатьобработка ошибок в функциях MySQLi, в противном случае, если результат не будет возвращен, массив будет пустым.

Если у вас есть какие-либо вопросы, пожалуйста, прокомментируйте, я с удовольствием помогу вам.

РЕДАКТИРОВАТЬ: Я неНе думаю, что возможно сделать то, что вы пытались достичь исключительно в MySQL, и я не думаю, что это нужно делать.Вот почему я объединил PHP с MySQL.

Кроме того, в зависимости от того, сколько у вас может быть тысяч продаж, было бы не очень хорошей идеей получить все результаты продаж в большом запросе.В качестве решения вы можете найти их специально для магазина.Изменения, которые необходимо внести в код, - это то, что SQL должен выглядеть так:

SELECT *
FROM table_sales
WHERE shop = ?
ORDER BY day ASC

И затем удалите эту строку, так как она становится ненужной:

if($total_sales[$i]["shop"] == $daily_sales[$j]["shop"])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...