0

Table Sales

date        id_product  total sales
2018-10-01  1             40
2019-09-01  1             20
2019-11-01  1             5
2019-12-01  1             40
2020-01-01  1             10  
2020-02-01  1             15    
2020-03-01  1             20
2020-08-01  1             10
2021-01-01  1             5
2021-02-01  1             8
2021-04-01  1             12

Table Product

id      name
1       Book
2       Pen

How to query in MySql to get the number (serial/sequential number) and the total cumulative sales with an interval of 3 years to get results like this?

number name  date  sum_sales   cummulative_sales
1      Book  2018  40          40
2      Book  2019  65          105
3      Book  2020  55          160
4      Book  2021  25          145
Pamungkas
  • 15
  • 5

2 Answers2

1

Assuming you are running MySQL 8+, you may try using SUM as an analytic function:

SELECT
    ROW_NUMBER() OVER (PARTITION BY p.name ORDER BY YEAR(s.date)) number,
    p.name,
    YEAR(s.date) AS date,
    SUM(s.total_sales) AS sum_sales,
    SUM(SUM(s.total_sales)) OVER (PARTITION BY p.name ORDER BY YEAR(s.date)) AS cummulative_sales
FROM Sales s
INNER JOIN Product p
    ON p.id = s.id_product
GROUP BY
    p.name,
    YEAR(s.date)
ORDER BY
    p.name,
    YEAR(s.date);
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • the cumulative_sales value is incorrect. I want to make interval in 3 years in cumulative_sales. Example the value for 2020 is cumulative beetween 2018-2020 and the value for 2021 is cymulative beetween 2019-2021 – Pamungkas May 16 '21 at 11:31
-1

Using MySQL 5.7, this will give you a sum and a cumulative sum of sales in a window of 3 years.

SELECT (@row = @row + 1) AS number, name, YEAR(date) AS date, 
SUM(total_sales) as sum_sales,
iF(
    @window > 0, 
    @cummulative_sales := @cummulative_sales + SUM(total_sales), 
    @cummulative_sales := SUM(total_sales)
) AS cummulative_sales,
@window := @window + 1,
@window := @window % 3

FROM Sales
JOIN Product ON Sales.id_product = Product.id,
(
    SELECT @row := 0, @cummulative_sales := 0, @window := 0
) as a
GROUP BY name, YEAR(date);
aRvi
  • 2,203
  • 1
  • 14
  • 30
  • Please test code before posting, and note that this kind of method is essentially deprecated – Strawberry May 16 '21 at 05:52
  • which kind of method is deprecated @Strawberry – aRvi May 16 '21 at 05:54
  • @variables - and in any event, this isn't (wasn't) the right way to use them – Strawberry May 16 '21 at 05:56
  • https://stackoverflow.com/a/24673769/5460261 @variables is being used and it's working as well, how is it not the right way to use them. If it's not the right way to use them then what is the right way – aRvi May 16 '21 at 05:58
  • No, back in 2014 that usage was also incorrect (although OMG Ponies has a correct example at that same link) – Strawberry May 16 '21 at 06:00
  • https://stackoverflow.com/a/2564009/5460261 in the first answer OMG Ponies mentioned using the cross join which is the same that I have written. And OMG Ponies has written the same answer. using JOIN or cross JOIN has the same complexity in this scenario – aRvi May 16 '21 at 06:04
  • @aRvi I believe your approach is deprecated as of MySQL 8+. Not sure if it would be considered valid before that. – Tim Biegeleisen May 16 '21 at 06:06
  • You haven't tested your code. But anyway, it's beside the point. When used correctly, this method was valid 5 years ago. It's not valid today. – Strawberry May 16 '21 at 06:07
  • What is valid today then? – aRvi May 16 '21 at 06:09
  • can you share any valid resource that it is not valid? – aRvi May 16 '21 at 06:11
  • See TB's answer. And https://dev.mysql.com/doc/refman/8.0/en/user-variables.html , which points out that defining user variables in this way is maintained for backwards compatibility only. – Strawberry May 16 '21 at 06:17
  • Ok, I have changed to Mysql 5.7 in the answer. I have not worked on MySQL 8, so I don't have any idea about new features in MySQL 8. Will this query will give an error in MySQL 8? – aRvi May 16 '21 at 06:25
  • @aRvi It _might_ work on MySQL 8, but the point is that it might break on future versions of MySQL. Also, even if it works, it won't port to any other SQL database (save perhaps an early version of MariaDB). – Tim Biegeleisen May 16 '21 at 08:27