I want to calculate sum of last N elements in a database table for each row, I tried various approaches but i can;t find any way to do this in a single query.
This is what I have, let's say N is 2, and I have this data,
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
I want the following result
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
Is it even possible to do this in single query?
In MySQL 8+, just use 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;
In older versions, use a 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;
May I suggest the following idea:
sales
ordered by shop ASC, day ASC
. sales
according to numberOfDays
in an array. Here is the full example in PHP, but you can use any language that goes with MySQL as you like:
$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);
The $total_sales
is a multi-dimensional array. You can access it like this for example: $total_sales[0]["sales"]
and it will give you the total amount of the sales for a numberOfDays
for a specific shop that you can see in $total_sales[0]["shop"]
.
Remember to make error handling in the MySQLi functions otherwise if no result is returned the array will be empty.
If you any questions please comment, I'll gladly help you out.
EDIT: I don't think its possible to do what you were trying to achieve solely in MySQL, neither do I think one is supposed to. That is why I combined PHP with MySQL.
Also, depending on whether you might have many thousands of sales, it might not be a good idea to retrieve all the sales results in a massive query. As a solution you can retrieve them shop-specifically. The changes that have to be made to the code is that the SQL has to look like this:
SELECT *
FROM table_sales
WHERE shop = ?
ORDER BY day ASC
And then remove this line, as it becomes unnecessary:
if($total_sales[$i]["shop"] == $daily_sales[$j]["shop"])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.