Show total of values by month - php

I have a simple table that shows invoices and the date they were created. I am looking for a way to show the total of the invoices values at the bottom of the last row of every month while showing the table.
Example:
Date
Amount
04-05-2020
$50
02-05-2020
$30
14-05-2020
$10
TOTAL
$90
Date
Amount
04-07-2020
$15
02-07-2020
$15
14-07-2020
$15
TOTAL
$45
Any idea? This is what I have so far:
<!DOCTYPE html>
<html>
<head>
<title>FACTURAS</title>
<style>
table, th, td {
border: 1px solid black;
}
</style>
</head>
<body>
<?php
$server = "localhost";
$user = "root";
$password = "";
$db = "facturas";
$conn = new mysqli($server, $user, $password, $db);
if ($conn->connect_error) {
die("CONNECTION ERROR " . $conn->connect_error);
}
$sql = "SELECT * FROM facturas_table ORDER BY id";
$facturas = $conn->query($sql);
echo '<table>
<thead>
<tr>
<td>ID</td>
<td>DATE</td>
<td>INVOICE</td>
<td>PRICE</td>
</tr>
</thead>';
while ($row = $facturas->fetch_assoc()) {
$month = substr($row['fecha'], 3);
// $totalMonths = "SELECT SUM(monto) as montoTotal FROM facturas_table WHERE fecha = ''"
echo '
<tbody>
<tr>
<td>'.$row['id'].'</td>
<td>'.$row['fecha'].'</td>
<td>'.$row['factura'].'</td>
<td>'.$row['monto'].'</td>
</tr>
</tbody>';
}
echo '</table>';
?>
</body>
</html>

First of all try to divide html from php if anyhow possible, as the mix will create problems in the future. Also try to use english language for all variable names (I assume monto is the price).
What I got from your question is, that you try to create the table and also calculate the total. Therefor you would create a variable for the sum and add the current amount of each row to the sum variable (in each iteration of the loop).
I changed the relevant php part:
UPDATED to your comment (sorry this was not so clear from your question).
Important is the trick with $lastMonth and $month, as well as with $first
<tbody>
<?php
$total = 0; $lastMonth = ""; $first = true;
while ($row = $facturas->fetch_assoc()) :
$month = substr($row['fecha'], 3);
$total += $row['monto']; ?>
<?php if(!$first && $lastMonth != $month): ?>
<tr>
<th colspan="2">Total (<?=$month?>): </th>
<th colspan="2"><?=$total?></th>
</tr>
<?php $total=0; endif; ?>
<tr>
<td><?=$row['id']?></td>
<td><?=$row['fecha']?></td>
<td><?=$row['factura']?></td>
<td><?=$row['monto']?></td>
</tr>
<?php $first=false; $lastMonth = $month; endwhile; ?>
<tr>
<th colspan="2">Total (<?=$month?>): </th>
<th colspan="2"><?=$total?></th>
</tr>
</tbody>
</table>
didn't try out the code (so be sure to check for syntax), but you can get the idea how to do that pretty well

while #helle's answer focuses on a solution on PHP side, here's an answer on the database side:
create table `facturas_table`(`id` bigint primary key, `invoice` varchar(100), `price` bigint, `date` date);
insert into `facturas_table` (`id`, `invoice`, `price`, `date`) values
(1, "A25C45", 5000, str_to_date("04-05-2020", "%d-%m-%Y")),
(2, "A25C46", 3000, str_to_date("02-05-2020", "%d-%m-%Y")),
(3, "A25C47", 1000, str_to_date("14-05-2020", "%d-%m-%Y")),
(4, "A25C48", 1500, str_to_date("04-07-2020", "%d-%m-%Y")),
(5, "A25C49", 1500, str_to_date("02-07-2020", "%d-%m-%Y")),
(6, "A25C50", 1500, str_to_date("14-07-2020", "%d-%m-%Y"))
;
select * from (
select `id`, `invoice`, `price`, date_format(`date`, "%d-%m-%Y") `date`, date_format(`date`, "%Y-%m-%d") `ordering_format` from `facturas_table`
union all
select null `id`, null `invoice`, `price`, `month` `date`, date_format(str_to_date(concat("01-", `month`), "%d-%m-%Y"), "%Y-%m-32") `ordering_format` from (
select sum(`price`) `price`, date_format(`date`, "%m-%Y") `month` from `facturas_table` group by `month`
) `totals`
) `a` order by `ordering_format` asc;
From there on
<-- Some Code -->
<table>
<thead>
<tr>
<th>ID</th>
<th>DATE</th>
<th>INVOICE</th>
<th>PRICE</th>
</tr>
</thead>
<tbody>
<?php while($row = $facturas->fetch_assoc()): ?>
<?php if ($row["invoice"] === null): ?>
<tr style="font-size: bolder">
<td colspan="2">Total <?php echo $row["date"]; ?></td>
<td colspan="2"><?php echo $row["price"]; ?></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>ID</th>
<th>DATE</th>
<th>INVOICE</th>
<th>PRICE</th>
</tr>
</thead>
<tbody>
<?php else: ?>
<tr>
<td><?php echo $row["id"]; ?></td>
<td><?php echo $row["date"]; ?></td>
<td><?php echo $row["invoice"]; ?></td>
<td><?php echo $row["price"]; ?></td>
</tr>
<?php endif; ?>
<?php endwhile; ?>
<-- Rest of Code -->
Note that since date is a reserved keyword in MySQL, it is wrapped in backticks (`). It is good practice to wrap any user-defined names (even if they are not reserved) in backticks to avoid confusion and unnecessary and hard-to-catch syntactic bugs.
Also Note that price is written in cents and its type is bigint. It's also good practice that:
Use bigint for integer primary keys on tables that are going to be massive in the long run and most probably getting archived in a warehouse in the future, too. That way you have plenty of time before rotating IDs, better still, use some long guaranteed unique values like UUIDs and GUIDs as primary key. In this case, if invoice numbers are going to be unique, it's best to be chosen as ID since it's the natural ID of this kind of records.
Use the smallest possible currency of the target market, this way you will avoid using decimals (which are inefficient) or worst floating point numbers (which are terrible at precision, since computers work in base 2 and humans work in base 10). Also, if you needed to divide any currency values (like calculating rebate and discounts), always use the same rounding policy on the smallest currency. For example, if you are going to give a 10% discount on an item with 9.95$, you can choose the policy to round discount up (to avoid customer dissatisfaction), but stick to it all the time, also use BCD operations since they are calculating values like humans do and not like computers do, but are expensive. Use them in sensitive error prone situations like this (not just adding simple integers, but divisions and multiplies)
$price = 995;
$discount = 10;
$discounted_value = explode(".", bcdiv(bcmul($price, $discount, 2), "100", 2), 2);
$discounted_value = $discounted_value[0] + (($discounted_value[1] + 0) !== 0);
$final_price = $price - $discounted_value;
Finally, if you think you are going to deal prices greater than PHP_INT_MAX (take care that it's different in 32-bit and 64-bit versions), just go full berserk mode and use strings in combination of bcmath operations for prices.
Having a good online business!

Related

php table <th> and <td> from Database Selected but they are not Matching in the right indexing position

all Developers.
I am developing School Management System, in the Database, I have two tables one is For Subjects, and the other one is designed for obtained marks of the Subjects and it is called scores.
So I am trying to fetch subject Names as Table Head
I have another Query below this query and I am trying to fetch from scores as table data .
At this point, I failed to match the subject name and its score from the scores table.
Here is my code:
<table class="table table-striped table-bordered">
<head>
<tr>
<?php
// Query for Subject Names
$view_subject = $config->prepare("SELECT * FROM subjects");
$view_subject->execute();
while($row = $view_subject->fetch()){
$sub_name = htmlspecialchars($row['sub_name']);
?>
<th class="text-center"style="background-color:#395C7F;color:#fff;"><?php echo $sub_name;?></th>
<?php } ?>
</tr>
</thead>
<body>
<?php
// Query for Subject Scores
$view_scores = $config->prepare("SELECT * FROM scores INNER JOIN subjects ON scores.score_sub_id = subjects.sub_id WHERE scores.std_rand = :random_id ORDER BY scores.score_sub_id ASC");
$view_scores->execute(['random_id' => $rand_ID]);
while($row = $view_scores->fetch()){
$score_id = htmlspecialchars($row['score_id']);
$score_sub_id = htmlspecialchars($row['score_sub_id']);
$score_mid_amount = htmlspecialchars($row['score_mid_amount']);
$score_final_amount = htmlspecialchars($row['score_final_amount']);
?>
<tr>
<td class="text-black" data-title="Subject"><?php echo $score_mid_amount;?></td>
</tr>
<?php } ?>
</tbody>
</table>
Database images:
1- Subjects table
2- Scores table
** Browser UI **
On your second loop you have entered '<tr>' wrapping each '<td>' that means that each one arrives at a different line , '<td>'s should be as much as there are '<th>' for each line.... so :
<?php
// Query for Subject Scores
$view_scores = $config->prepare("SELECT * FROM scores INNER JOIN subjects ON scores.score_sub_id = subjects.sub_id WHERE scores.std_rand = :random_id ORDER BY scores.score_sub_id ASC");
$view_scores->execute(['random_id' => $rand_ID]);
?>
<tr>
<?php
while($row = $view_scores->fetch()){
$score_id = htmlspecialchars($row['score_id']);
$score_sub_id = htmlspecialchars($row['score_sub_id']);
$score_mid_amount = htmlspecialchars($row['score_mid_amount']);
$score_final_amount = htmlspecialchars($row['score_final_amount']);
?>
<td class="text-black" data-title="Subject"><?php echo $score_mid_amount;?></td>
<?php } ?>
</tr>
</tbody>
</table>
This should fix your table but it will only create one line! if you have more than one line you will need to add another loop to wrap this one and it will create the new '<tr>' outside the inner loop.
BTW: I assume that the 2nd while loop is exactly long as the first one... since you are supposed to have the same amount of <td> per line per <th> if it's not in the same length or not sorted the same way you will have an issue... which can be resolved either by adjusting your SELECT or creating an array with ids and injecting to it the data from the second loop according to the keys brought in the first.

Returns all rows with Minimum Value in Php

I have a table that consist of records and i want to retrieve rows with minimum price. I try the code below, and i am only able to retrieve only one rows. i need to return all rows with minimum price for the same partno.
<tr>
<th>S/N</th>
<th>Part Number</th>
<th>Description </th>
<th nowrap="nowrap">Recommended Price</th>
<th nowrap="nowrap">Recommended Supplier</th>
</tr>
<?php
$get = mysqli_query($con,"SELECT MIN(price)As price,partno,supplier,description FROM tab_stockqty2 ");
$c=0;
while($rw = mysqli_fetch_array($get)){
$c++;?>
<tr>
<td nowrap="nowrap"><?php echo $c;?></td>
<td nowrap="nowrap"><?php echo $rw['partno'];?></td>
<td nowrap="nowrap"><?php echo $rw['description'];?></td>
<td><?php echo number_format($rw['price'],2);?></td>
<td><?php echo $rw['supplier'];?></td>
</tr>
<?php };?>
See Database Record:
It show return two rows, but it is only retuning only one row for the first set of partno-2070081
To retrieve all records with minimal price, per partno, the query should be something like this:
SELECT s.price,s.partno,s.supplier,s.description FROM tab_stockqty2 s
INNER JOIN (
SELECT MIN(price) as m, partno FROM tab_stockqty2 GROUP BY 2
) m on s.price = m.m and s.partno = m.partno
Demo: http://sqlfiddle.com/#!9/3e089/1
try this ==>
SELECT MIN(price)As price,partno,supplier,description FROM tab_stockqty2 group by partno
The SQL MIN returns only 1 row which is the most minimum.
What you can do is fetch all records and sort them on price based on ascending order.
SELECT price,partno,supplier,description FROM tab_stockqty2 ORDER BY price ASC;
Try this instead.
In this way you will get records based on price from Low to High.

Sum specific keys in SQL query - PHP

I have a SQL query that returns all fields in a table:
$registro = mysqli_query($con,
"SELECT * FROM agenda ORDER BY procedimento LIMIT $limit, $nroLotes");
My question is, if possible, through this query, sum the particular column values associated with another column of values, eg
Among other columns there are "Column: Name" where the values are names and "Column: Value" where the values are numbers. The idea is to add up the values associated with the names.
I suppose I do a foreach inside the while, but I have difficulty in this approach.
The following piece code in question:
<?php
//...
$registro = mysqli_query($con, "SELECT * FROM agenda ORDER BY procedimento LIMIT $limit, $nroLotes");
$tabela = $tabela.'<table class="table table-striped table-condensed table- hover">
<tr>
<th width="300">Nome</th>
<th width="200">Procedimentos</th>
<th width="150">Valor Cobrado do serviço</th>
<th width="150">Valor Total dos serviços</th>
<th width="150">Porcentagem do Valor Total dos serviços</th>
<th width="150">Data</th>
</tr>';
while($linha = mysqli_fetch_array($registro)){
$porcentagem = ($linha['valor'] * 30) / 100;
$tabela = $tabela.'<tr>
<td>'.$linha['nome_funcionario'].'</td>
<td>'.$linha['procedimento'].'</td>
<td>'.number_format($linha['valor'], 2, ',', '.').'</td>
<td>'.number_format($porcentagem).'</td>
<!--cell containing the sum-->
<!--<td>'.number_format($sum).'</td>-->
<td>'.fechaNormal($linha['start']).'</td>';
}
$tabela = $tabela.'</table>';
$array = array(0 => $tabela,
1 => $lista);
echo json_encode($array);
?>
I enjoy some light ;)

How to remove duplication in the retrieval results?

Please i need a help am beginner in php and my sql, i want to retrieve all students names who registered in each level(1 OR 2 OR 3 OR 4) this is my code.
<form id="form1" name="form1" method="post" action="">
<table border="1" align="center" class="tftable">
<?php
$lvlid = $_GET['id'];
$sql2 = "select * from `course` where acadlevel='$lvlid' ";
$res2= mysql_query($sql2,$con_mark_entry);
while($row2 = mysql_fetch_row($res2))
{?>
<?php } ?>
<tr>
<th id="h7">Serial NO.</th>
<th id="h7">Student NO.</th>
<th id="h7">Student Name</th>
</tr>
<?php
$s=1;
$sql ="SELECT student.stud_id,student.stud_name, course.title, enrollment.grade FROM student, course, enrollment WHERE course.acadlevel ='".$_GET['id'] ."' AND course.code = enrollment.code AND student.stud_id = enrollment.stud_id";
$res= mysql_query($sql,$con_mark_entry);
while($row1 = mysql_fetch_row($res)){
?>
<tr>
<td><?php echo $s?> </td>
<td><?php echo $row1[0]?></td>
<td id="name"><a href="report6.php?id=<?php echo $row1[1]?>"> <?php echo $row1[1]?> </td>
</tr>
<?php
$s++;
}
?>
</table>
My Problem is for example if the student registered in three course at level 1 ,he would appear three times, i want to remove this duplication. HOW?
The result as follow:
serial no student no student name
1 101 adam nagdy
2 101 adam nagdy
3 101 adam nagdy
4 102 shima najm
Thanks in advance
Use DISTINCT keyword. It removes duplicate result rows.
Search for "distinct" in this page.
SELECT DISTINCT std.stud_id,std.stud_name, enr.grade -- , crs.title
FROM student std
LEFT OUTER JOIN enrollment enr ON std.stud_id = enr.stud_id
LEFT OUTER JOIN course crs ON crs.code = enr.code
WHERE course.acadlevel ='YOUR_ID'
And use JOIN to join. ;) It is better than joining with WHERE (even if it works).
Try using GROUP BY course.acadlevel at the end of your query.
That should reduce the results to one row per academic level, instead of 3, if the student registered for 3 classes.
Also, as John Conde has commented, mysql_ prefixed functions are deprecated and will be removed from future versions of PHP. You should instead use Mysqli or PDO_MySQL. And you should never use $_GET[]/$_POST or any other variables with user input in your MySQL queries without sanitizing them.

How to get the sum of table column?

I have a column name quantity, unit_price and total_amount. The total_amount field in my database set to zero, in my query I used SUM(unit_price*quantity) AS total_amount to get the total value as total_amount. But when I tried to get the sum of total amount as total_sum is always get 0. if is it because the total_amount field in my database is set to zero? What I want to do is get the SUM(total_amount) AS total_sum but it always displays 0.
This is my Query.
<?php
$mysqli = new mysqli("localhost", "root", "", "app");
$term = $_GET['supp'];
$result = $mysqli->query("SELECT *, SUM(unit_cost*quantity) AS total_amount FROM procurement WHERE supplier LIKE '%".$term."%' GROUP BY counter");
echo'<table id="tfhover" cellspacing="0" class="tablesorter" style="text-transform:uppercase;" border="1px">
<thead>
<tr>
<th>SUPPLIER</th>
<th>ITEM</th>
<th>DESCRIPTION</th>
<th>QTY</th>
<th>UNIT</th>
<th>UNIT PRICE</th>
<th>Total Amount</th>
</tr>
</thead>';
echo'<tbody>';
while($row = $result->fetch_assoc()){
echo'<tr>
<td>'.$row['supplier'].'</td>
<td>'.$row['item_name'].'</td>
<td>'.$row['item_description'].'</td>
<td>'.$row['quantity'].'</td>
<td>'.$row['unit'].'</td>
<td>'.number_format($row['unit_cost'], 2, '.', ',').'</td>
<td>'.number_format($row['total_amount'], 2, '.', ',').'</td>
</tr>';
}
echo'<TR> <TD COLSPAN=6 BGCOLOR="#99CCFF">TOTAL AMOUNT</TD> <td>'.number_format($row['total_sum'], 2, '.', ',').'</td></TR>';
echo "</tbody></table>";
?>
My another problem is when I insert this code echo' TOTAL AMOUNT '.number_format($row['total_sum'], 2, '.', ',').''; inside the while loop. I want to have just 1 total amount row.
SELECT *, SUM(unit_cost*quantity) AS total_amount FROM procurement WHERE supplier LIKE '%".$term."%' GROUP BY counter"
This is a select statement which would not update any data in the database.
It seems that your total_amount, which can be evaluated every time when you need it, is not necessarily exists as a column in your table.
Also, can you post your table structure ? Actually the SQL seems not correct anyway.

Categories