Home > OS >  SQL query calculate and display sum data per each of the past 12 months
SQL query calculate and display sum data per each of the past 12 months

Time:10-06

I am trying to create a chart where by i will display data from my scores table and that data must be per the total scores from each month. I am a novice when it comes to advanced sql queries. I have tried following some examples on SO but still haven't got it yet.

Below is the scores table

---------------------------------
id     | marks  | date_created   
---------------------------------
1      |   100  |  2020-03-12
2      |   90   |  2020-08-25
3      |   100  |  2021-04-10
4      |   95   |  2021-06-20
5      |   99   |  2021-10-02
6      |   97   |  2021-10-02

What i want to do is make sure that when i display the chart, it will show scores from the past 12 months and zeros where those months don't have scores.

#Edit 3 The table below is just a visualisation of what i want to achieve. I dont have it yet in the database. I only have the scores table

---------------------------------
month        |   sum(marks)
---------------------------------
October      |   0
September    |   0
August       |   0
July         |   0
June         |   95
May          |   0
April        |   100
March        |   100
February     |   0
January      |   0
December     |   0
November     |   0

As you can notice in the table, i want the latest month to be what's sorted last How can i achieve this? Thanks

Edit #1

The marks from the different scores are summations of marks from total days in individual months. As you can notice on the scores table, there's a day with 2 score entries. In my totals i would like for those scores to all be computed for the month of October.

Edit #2


function get_last_12_month_scores(){
    $db = Database::getInstance();
    $mysqli = $db->getConnection();
    $user_id = $_SESSION['user_id'];

    $query_count = "SELECT SUM(`marks`) as `total` FROM `scores` WHERE `user_id`='$user_id';

    $month_12_query_count =
        "SELECT
            SUM(IF(month = 'Jan', total, 0)) as 'Jan',
            SUM(IF(month = 'Feb', total, 0)) as 'Feb',
            SUM(IF(month = 'Mar', total, 0)) as 'Mar',
            SUM(IF(month = 'Apr', total, 0)) as 'Apr',
            SUM(IF(month = 'May', total, 0)) as 'May',
            SUM(IF(month = 'Jun', total, 0)) as 'Jun',
            SUM(IF(month = 'Jul', total, 0)) as 'Jul',
            SUM(IF(month = 'Aug', total, 0)) as 'Aug',
            SUM(IF(month = 'Sep', total, 0)) as 'Sep',
            SUM(IF(month = 'Oct', total, 0)) as 'Oct',
            SUM(IF(month = 'Nov', total, 0)) as 'Nov',
            SUM(IF(month = 'Dec', total, 0)) as 'Dec',
            SUM(total) as total_yearly
        FROM (
            SELECT DATE_FORMAT(date_added, '%b') as month, SUM($query_count as total
            FROM scores
            WHERE date_added <= now() and date >= Date_add(now(),interval - 12 month)
            GROUP BY DATE_FORMAT(date_added, '%m-%Y'))) as sub";

    $query_result = $mysqli->query($month_12_query_count);

    echo $query_result;
}

With echo $query_result; i echoed to see if $query_result would give me an array such that i could be able to capture the individual values in the array by doing get_last_12_month_scores()[i] in the Chart.js data values script. But it unfortunately didn't

It's at this that i realised i was either not aware what i was doing or had to just seek help to avoid wasting time.

CodePudding user response:

Here is a track :

SELECT
 sum(case when month(date_created) = 10 then marks else 0 end) October,
 sum(case when month(date_created) = 9 then marks else 0 end) September,
 sum(case when month(date_created) = 8 then marks else 0 end) August,
 sum(case when month(date_created) = 7 then marks else 0 end) July,
 sum(case when month(date_created) = 6 then marks else 0 end) June,
 sum(case when month(date_created) = 5 then marks else 0 end) May,
 sum(case when month(date_created) = 4 then marks else 0 end) April,
 sum(case when month(date_created) = 3 then marks else 0 end) March,
 sum(case when month(date_created) = 2 then marks else 0 end) February,
 sum(case when month(date_created) = 1 then marks else 0 end) January,
 sum(case when month(date_created) = 12 then marks else 0 end) December,
 sum(case when month(date_created) = 11 then marks else 0 end) November
FROM scores 
GROUP BY month(date_created)

CodePudding user response:

My solution does not add a value for empty months, which could be dealt with when rendering the output in your php, but does differentiates between years. Otherwise, to get the missing months you could create an extra table to cross reference, see this thread:

SELECT YEAR(date_created), MONTH(date_created), sum( mark )
FROM scores
GROUP BY YEAR(date_created), MONTH(date_created)

Or to select a specific year you can do:

SELECT MONTH(date_created), sum(mark)
FROM scores
WHERE YEAR(date_created) = 2020 -- target year
GROUP BY MONTH(date_created)

Fiddle here: http://sqlfiddle.com/#!9/f5f62e/1

-- create a table
CREATE TABLE scores (
  id INTEGER PRIMARY KEY,
  mark INTEGER NOT NULL,
  date_created date NOT NULL
);

-- insert some values
INSERT INTO scores VALUES (1, '100', '2020-03-12');
INSERT INTO scores VALUES (2, '90', '2020-08-25');
INSERT INTO scores VALUES (3, '100', '2021-04-10');
INSERT INTO scores VALUES (4, '95', '2021-06-20');
INSERT INTO scores VALUES (5, '99', '2021-10-02');
INSERT INTO scores VALUES (6, '99', '2021-10-05');
  • Related