Here are the 2 tables structures (minified for a MCVE - they have more rows not needed here):
++++++++++++++++++++++++++++++++ FEES ++++++++++++++++++++++++++++++++++
fee_id +++ fee_amount +++ fee_date +++ fee_student_ID +++ fee_paid +++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 +++ 200 +++ 2019-12-05 +++ 1 +++ N ++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 +++ 200 +++ 2020-01-05 +++ 1 +++ N ++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 +++ 200 +++ 2020-01-05 +++ 1 +++ N ++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 +++ 250 +++ 2020-01-05 +++ 2 +++ N ++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 +++ 250 +++ 2020-02-05 +++ 2 +++ N ++++
The tables are linked -> fee_student_ID = student_ID
++++++++++++++++++++ STUDENTS +++++++++++++++++++++
student_ID +++ student_name +++ student_phone +++
+++++++++++++++++++++++++++++++++++++++++++++++++++
1 +++ John Doe +++ 123456789 +++
+++++++++++++++++++++++++++++++++++++++++++++++++++
2 +++ Jane Doe +++ 987654321 +++
With my SQL query, I can retrieve and order the data (I need only rows where "paid" is late/coming soon). What I need is:
- group by year
- sum amount by year
I achieve #1 like this (and it works as expected):
$pdo = new PDO("mysql:host=localhost;dbname=$dbname", $adminDBuser, $adminDBpwd);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
$stmt = $pdo->prepare(" SELECT tbl_fees.*, tbl_students.*, YEAR(tbl_fees.fee_date) AS yearfee
FROM tbl_fees, tbl_students
WHERE tbl_fees.fee_student_ID=tbl_students.student_ID
AND tbl_fees.fee_paid='N'
AND tbl_fees.fee_date <= DATE_ADD(NOW(), INTERVAL 7 DAY)
ORDER BY tbl_fees.fee_date ");
$stmt->execute();
$results = $stmt->fetchAll();
foreach( $results as $row ) {
if ($row['yearfee'] != $yearfee) {
echo "<tr colspan=\"5\" class=\"table-title-year\"><td class=\"table-title-year\">
". $row['yearfee']."
</td></tr>";
//**-- adds a row on top of the list, with the YEAR, and splits the data => OK
}
echo"<tr><td>$fee_id</td><td>",my_formated_date($fee_date),"</td>
<td><a href=\"/student-data.php?id=$student_ID\">$student_name</a></td>
<td>$fee_amount</td><td>$fee_paid</td></tr>\n\r";
}
Now, what I want to add is another, at the bottom of each "year split". This row would show the total amount of unpaid/soon to be paid fees. Like below, which is the expected outcome:
-----------------------------------------
YEAR : 2019
-----------------------------------------
1 --- John Doe --- 2019-12-05 --- 200 ---
-----------------------------------------
TOTAL : 200
-----------------------------------------
YEAR : 2020
-----------------------------------------
2 --- John Doe --- 2020-01-05 --- 200 ---
3 --- Jane Doe --- 2020-01-05 --- 250 ---
4 --- John Doe --- 2020-02-05 --- 200 ---
5 --- Jane Doe --- 2020-02-05 --- 250 ---
-----------------------------------------
TOTAL : 900
-----------------------------------------
How do I achieve the above table, using SQL query or PHP?
I've searched the MySQL (and other related topics in the doc) and this tutorial (amongst others), but can't find a way to adapt it to my case.
I've tested something like this, with a single year or for each known separate year (all throwing errors anyway...):
- SUM(tbl_fees.fee_amount) FILTER (WHERE EXTRACT(YEAR FROM tbl_fees.fee_date) = 2019) AS yearlySumTotal1
- SUM(tbl_fees.fee_amount) WHERE EXTRACT(YEAR FROM tbl_fees.fee_date) = '2019' AS yearlySumTot1
<?php
$results = [
['id' => 1, 'name' => 'John Doe', 'date' => '2019-12-05', 'amount' => 200],
['id' => 2, 'name' => 'John Doe', 'date' => '2020-01-05', 'amount' => 200],
['id' => 3, 'name' => 'John Doe', 'date' => '2020-01-05', 'amount' => 250],
['id' => 4, 'name' => 'John Doe', 'date' => '2020-02-05', 'amount' => 200],
['id' => 5, 'name' => 'John Doe', 'date' => '2020-02-05', 'amount' => 250],
];
$year = '';
$total = 0;
echo '<pre>';
foreach ($results as $row) {
$rowyear = substr($row['date'], 0, 4);
if ($year != $rowyear) {
// avoid displaying in the begining of the table
if ($total) {
display_total_row($total);
}
display_year_row($rowyear);
$year = $rowyear;
$total = 0;
}
echo '-----------------------------------------' . PHP_EOL;
echo sprintf('%d --- %s --- %s --- %s ---', $row['id'], $row['name'], $row['date'], $row['amount']) . PHP_EOL;
echo '-----------------------------------------' . PHP_EOL;
$total += $row['amount'];
}
// display last total
display_total_row($total);
echo '</pre>';
function display_year_row($year) {
echo '-----------------------------------------' . PHP_EOL;
echo 'YEAR : ' . $year . PHP_EOL;
echo '-----------------------------------------' . PHP_EOL;
}
function display_total_row($total) {
echo '-----------------------------------------' . PHP_EOL;
echo 'TOTAL : ' . $total . PHP_EOL;
echo '-----------------------------------------' . PHP_EOL;
}