我为会计应用程序创建了一个API。我在一栏中有收入和支出。如何将所有收入和支出相加并减去?
这是我的代码:
private function list_recap() {
if($this->get_request_method() != "GET") {
$this->response('', 406);
}
$year = $this->_request['year'];
$month = $this->_request['month'];
$sqlPlus = $this->db->query("SELECT SUM(nominal)
FROM lap_keuangan
WHERE YEAR(tanggal) = '$year'
AND MONTH(tanggal) = '$month'
AND kategori = 1");
$sqlMin = $this->db->query("SELECT SUM(nominal)
FROM lap_keuangan
WHERE YEAR(tanggal) = '$year'
AND MONTH(tanggal) = '$month'
AND kategori = -1");
$result = array();
while($rowPlus = $sqlPlus->fetch(PDO::FETCH_ASSOC)) {
$plus = $result[] = $rowPlus;
}
while($rowMin = $sqlMin->fetch(PDO::FETCH_ASSOC)) {
$minus = $result[] = $rowMin;
}
$this->response($this->json($result), 200);
}
答案 0 :(得分:1)
使用一个SELECT语句来检索" plus"," minus"和"总计"。我们可以使用条件聚合。给定WHERE子句中的条件可以保证kategori
的值为1或-1,我们可以将nominal
乘以该值,并将其与SUM相加。
虽然我们正在努力,但我们应该清除SQL Injection漏洞。我们从不希望在SQL文本中包含可能不安全的值。
https://www.owasp.org/index.php/SQL_Injection
我们要么在包含它们之前正确地转义值,要么使用带有绑定占位符的预准备语句。 (它并不那么难;并且没有任何有效的理由不去做其中一个。)
为了提高性能,我们希望在 bare 列上有条件,而不是在表达式中包装列。如果tanggal
是DATE,DATETIME或TIMESTAMP数据类型,我们可以将该列的条件指定为值范围。 (如果有合适的索引,MySQL允许MySQL使用范围扫描操作,而不是评估表中每个行的表达式。)
我可能会将$year
和$month
值转换为yyyy-mm-01格式的字符串,然后将该日期字符串传递给查询。但是我们可以将$ year和$ month值传递给查询,并让MySQL将其转换为我们的日期。
这样的事情:
# static SQL text (no variable interpolation) mitigates SQL Injection
$sql =
"SELECT SUM( k.nominal * IF(k.kategori= 1 ,1,0) ) AS kat_plus
, SUM( k.nominal * IF(k.kategori= -1 ,1,0) ) AS kat_minus
, SUM( k.nominal * k.kategori ) AS kat_total
FROM lap_keuangan k
WHERE k.tanggal >= STR_TO_DATE(CONCAT( ? ,'-', ? ,'-01'),'%Y-%m-%d')
AND k.tanggal < STR_TO_DATE(CONCAT( ? ,'-', ? ,'-01'),'%Y-%m-%d') + INTERVAL 1 MONTH
AND k.kategori IN (-1,1)";
# prepare
$sth = $this->db->prepare($sql);
使用bindValue
为每个绑定占位符提供值并执行
# execute
$sth->bindValue(1, $year ,PDO::PARAM_STR);
$sth->bindValue(2, $month ,PDO::PARAM_STR);
$sth->bindValue(3, $year ,PDO::PARAM_STR);
$sth->bindValue(4, $month ,PDO::PARAM_STR);
$sth->execute();
或者使用位置绑定,我们可以跳过bindValue并只传递一个数组来执行:
# execute
$sth->execute(array($year,$month,$year,$month));
然后获取行,并访问数组成员
$row = $sth->fetch(PDO::FETCH_ASSOC);
$kat_plus = $row['kat_plus'];
$kat_minus = $row['kat_minus'];
$kat_total = $row['kat_total'];
如果PDO没有被配置为抛出异常,即
$this->$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
然后添加每个PDO函数调用(准备,执行,获取)成功/失败的检查并处理代码中的错误。
答案 1 :(得分:0)
您可以使用CASE-THEN-ELSE
构造,尝试执行此SQL语句:
SELECT
SUM(CASE WHEN kategori = 1 THEN nominal ELSE 0 END) -
SUM(CASE WHEN kategori = -1 THEN nominal ELSE 0 END)
FROM lap_keuangan
WHERE
YEAR(tanggal) = '$year'
AND MONTH(tanggal) = '$month'
AND kategori = 1
PS:
您的代码容易受到SQL注入攻击。您不能使用字符串连接传递SQL查询参数。请改用PDO
并绑定参数。