按月显示总值
Show total of values by month
我有一个简单的 table 可以显示发票及其创建日期。我正在寻找一种方法来显示每月最后一行底部的发票总值,同时显示 table.
示例:
Date
Amount
04-05-2020
02-05-2020
14-05-2020
TOTAL
Date
Amount
04-07-2020
02-07-2020
14-07-2020
TOTAL
有什么想法吗?这是我目前所拥有的:
<!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>
首先,如果可能的话,尝试将 html 与 php 分开,因为混合会在未来产生问题。还尝试对所有变量名称使用英语(我假设 monto 是价格)。
我从你的问题中得到的是,你尝试创建 table 并计算总数。因此,您将为总和创建一个变量,并将每行的当前数量添加到总和变量(在循环的每次迭代中)。
我修改了相关的php部分:
已更新您的评论(抱歉,您的问题不是很清楚)。
重要的是 $lastMonth
和 $month
以及 $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>
没有尝试代码(所以一定要检查语法),但你可以很好地了解如何做到这一点
虽然@helle 的回答侧重于 PHP 方面的解决方案,但这是数据库方面的答案:
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;
从那时起
<-- 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 -->
请注意,由于 date
是 MySQL 中的保留关键字,因此用反引号 (`) 括起来。将任何用户定义的名称(即使它们未保留)包装在反引号中以避免混淆和不必要且难以捕捉的语法错误是一种很好的做法。
另请注意,价格以美分表示,其类型为 bigint
。这也是一个很好的做法:
- 将
bigint
用于表上的整数主键,这些表在长期 运行 中会非常庞大,并且很可能在未来也会被归档在仓库中。这样你在轮换 ID 之前有足够的时间,更好的是,使用一些长期保证的唯一值,如 UUID
s 和 GUID
s 作为主键。在这种情况下,如果发票编号是唯一的,最好选择它作为ID,因为它是这种记录的自然ID。
- 使用目标市场的尽可能小的货币,这样您就可以避免使用小数(效率低下)或最差的浮点数(精度很差,因为计算机以 2 为基数工作,而人类以 2 为基数工作10).此外,如果您需要除以任何货币值(如计算回扣和折扣),请始终对最小货币使用相同的舍入策略。例如,如果你打算给一个 9.95 美元的商品 10% 的折扣,你可以选择向上取整的政策(以避免客户不满意),但始终坚持下去,也使用
BCD
操作,因为它们像人类一样计算值,而不是像计算机那样计算值,但是很昂贵。在像这样敏感的容易出错的情况下使用它们(不仅仅是添加简单的整数,还有除法和乘法)
$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;
最后,如果您认为您要交易的价格大于 PHP_INT_MAX
(注意 32 位和 64 位版本不同),请进入完全狂暴模式并结合使用字符串bcmath
个价格操作。
网上生意不错!
示例:
Date | Amount |
---|---|
04-05-2020 | |
02-05-2020 | |
14-05-2020 | |
TOTAL |
Date | Amount |
---|---|
04-07-2020 | |
02-07-2020 | |
14-07-2020 | |
TOTAL |
有什么想法吗?这是我目前所拥有的:
<!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>
首先,如果可能的话,尝试将 html 与 php 分开,因为混合会在未来产生问题。还尝试对所有变量名称使用英语(我假设 monto 是价格)。
我从你的问题中得到的是,你尝试创建 table 并计算总数。因此,您将为总和创建一个变量,并将每行的当前数量添加到总和变量(在循环的每次迭代中)。
我修改了相关的php部分:
已更新您的评论(抱歉,您的问题不是很清楚)。
重要的是 $lastMonth
和 $month
以及 $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>
没有尝试代码(所以一定要检查语法),但你可以很好地了解如何做到这一点
虽然@helle 的回答侧重于 PHP 方面的解决方案,但这是数据库方面的答案:
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;
从那时起
<-- 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 -->
请注意,由于 date
是 MySQL 中的保留关键字,因此用反引号 (`) 括起来。将任何用户定义的名称(即使它们未保留)包装在反引号中以避免混淆和不必要且难以捕捉的语法错误是一种很好的做法。
另请注意,价格以美分表示,其类型为 bigint
。这也是一个很好的做法:
- 将
bigint
用于表上的整数主键,这些表在长期 运行 中会非常庞大,并且很可能在未来也会被归档在仓库中。这样你在轮换 ID 之前有足够的时间,更好的是,使用一些长期保证的唯一值,如UUID
s 和GUID
s 作为主键。在这种情况下,如果发票编号是唯一的,最好选择它作为ID,因为它是这种记录的自然ID。 - 使用目标市场的尽可能小的货币,这样您就可以避免使用小数(效率低下)或最差的浮点数(精度很差,因为计算机以 2 为基数工作,而人类以 2 为基数工作10).此外,如果您需要除以任何货币值(如计算回扣和折扣),请始终对最小货币使用相同的舍入策略。例如,如果你打算给一个 9.95 美元的商品 10% 的折扣,你可以选择向上取整的政策(以避免客户不满意),但始终坚持下去,也使用
BCD
操作,因为它们像人类一样计算值,而不是像计算机那样计算值,但是很昂贵。在像这样敏感的容易出错的情况下使用它们(不仅仅是添加简单的整数,还有除法和乘法)
$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;
最后,如果您认为您要交易的价格大于 PHP_INT_MAX
(注意 32 位和 64 位版本不同),请进入完全狂暴模式并结合使用字符串bcmath
个价格操作。
网上生意不错!