Php MySQL查询以显示所有已付款和未付款发票,其中发票可以有多个付款

Php MySQL查询以显示所有已付款和未付款发票,其中发票可以有多个付款,php,mysql,Php,Mysql,我有两张桌子,请看下面的结构。基本上,使用MySQL/PHP,我需要构造两个查询。一个用于显示已付款发票的列表,另一个用于显示未付款发票。一张发票可以有多笔付款。例如,一张100英镑的发票可以使用不同金额的任意数量的付款进行支付。发票也可以没有付款,这意味着全额余额未付 你能帮我查询一下吗 我自己也尝试过这个问题(参见),但我没有提到一张发票可以有多笔付款 表结构 CREATE TABLE IF NOT EXISTS `accounts_invoice` ( `invoice_id` int

我有两张桌子,请看下面的结构。基本上,使用MySQL/PHP,我需要构造两个查询。一个用于显示已付款发票的列表,另一个用于显示未付款发票。一张发票可以有多笔付款。例如,一张100英镑的发票可以使用不同金额的任意数量的付款进行支付。发票也可以没有付款,这意味着全额余额未付

你能帮我查询一下吗

我自己也尝试过这个问题(参见),但我没有提到一张发票可以有多笔付款

表结构

CREATE TABLE IF NOT EXISTS `accounts_invoice` (
  `invoice_id` int(11) NOT NULL AUTO_INCREMENT,
  `invoice_customer_type` tinyint(4) DEFAULT NULL,
  `invoice_customer` int(11) DEFAULT NULL,
  `invoice_date` date DEFAULT NULL,
  `invoice_due_date` date DEFAULT NULL,
  `invoice_property_id` int(11) DEFAULT NULL,
  `invoice_tenancy_id` int(11) DEFAULT NULL,
  `invoice_branch` int(11) DEFAULT NULL,
  `invoice_payment_terms` tinyint(4) DEFAULT NULL,
  `invoice_notes` text COLLATE utf8_bin,
  `invoice_total_amount_exc_vat` decimal(10,2) DEFAULT NULL,
  `invoice_total_vat_amount` decimal(10,2) DEFAULT NULL,
  `invoice_posted` tinyint(4) DEFAULT '0',
  `invoice_date_created` datetime DEFAULT NULL,
  `invoice_date_updated` datetime DEFAULT NULL,
  `invoice_date_posted` datetime DEFAULT NULL,
  `invoice_created_by` int(11) DEFAULT NULL,
  `invoice_updated_by` int(11) DEFAULT NULL,
  `invoice_posted_by` int(11) DEFAULT NULL,
  PRIMARY KEY (`invoice_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=87 ;

CREATE TABLE IF NOT EXISTS `accounts_invoice_payment` (
  `invoice_payment_id` int(11) NOT NULL AUTO_INCREMENT,
  `invoice_payment_date` date DEFAULT NULL,
  `invoice_payment_amount` decimal(10,2) DEFAULT NULL,
  `invoice_payment_method` tinyint(4) DEFAULT NULL,
  `invoice_payment_invoice_id` int(11) DEFAULT NULL,
  `invoice_payment_notes` text COLLATE utf8_bin,
  `invoice_payment_date_created` datetime DEFAULT NULL,
  `invoice_payment_date_updated` datetime DEFAULT NULL,
  `invoice_payment_created_by` int(11) DEFAULT NULL,
  `invoice_payment_updated_by` int(11) DEFAULT NULL,
  PRIMARY KEY (`invoice_payment_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=71 ;

也许是这样的?我有两个问题

<?php

try
{
    $s = $conn->query("SELECT * from accounts_invoice");
}
catch(PDOException $e)
{
    echo $e->getMEssage();
}

try
{
    $p = $conn->prepare("SELECT * from accounts_invoice_payment where invoice_payment_invoice_id = :id");
}
catch(PDOException $e)
{
    echo $e->getMEssage();
}
while($main_invoies = $s->fetch(PDO::FETCH_OBJ))
{
    $invc_sum=0;
    $invoiceid = $main_invoies->invoice_id;
    $totalAmount = ($main_invoies->invoice_total_amount_exc_vat) + ($main_invoies->invoice_total_vat_amount);
    $p->bindParam(':id', $invoiceid);
    while($sub_invoices = $p->fetch(PDO::FETCH_OBJ))
    {
        $invc_sum = $invc_sum + ($sub_invoices->invoice_payment_amount);
    }
    if($invc_sum == $totalAmount)
    {
        echo "Invoice Paid";
    }
    else
    {
        echo "Invoice unpaid";
    }
}
?>

尽可能少地使用PHP。它不是db引擎。即使在中等大小的数据集上,它也会产生巨大的阻力

模式: 一次完成所有任务: 逾期的: 全额支付: 信用证到期日:
选择i.invId、i.invAmt、ifnull(金额(p.amt)、0)作为已付,i.invAmt-ifnull(金额(p.amt)、0)作为到期
从发票一
左连接付款
关于p.invId=i.invId
其中i.custId=101
因维人分组

到期
我自己也尝试过查询
查询在哪里?
发票付款发票id
=
发票id
?您的数据和预期结果是什么?Michael当它们都自动递增时,如何
发票付款发票id==发票id
相同的查询将显示所有已付款。负应付AMT是超额支付。祝你好运你是说“WHERE due=0”?是的,我相信你在去之前不能在查询中引用“due”。测试了所有4个。你可能需要一个或两个非常好的工作,谢谢!工作完美,是一个非常有效的解决方案!您的查询仍然返回所有发票,然后使用if语句处理它们。我希望查询只返回所有已付或未付发票。请上传一些测试数据好吗?您的解决方案确实有效,但效率不如公认的答案。@MichaelLB很高兴您找到了解决方案:)它确实有效,只是速度不如akshay。永远不要在php中做mysql可以做得更快的事情。想象一下10k行返回,而sql会给你答案。PHP是一件很棒的事情。。。一个高性能的数据库引擎,它不是
CREATE TABLE invoice
(
  invId int auto_increment primary key,
  custId int(11) not null,
  invAmt decimal(10,2) not null
);

CREATE TABLE payment
(
  pdId int auto_increment primary key,
  invId int not null,
  amt decimal(10,2) not null
);

-- NOTE you need foreign key (FK) constraints on your real table

insert invoice (custId,invAmt) values (101,9999);   -- 1
insert invoice (custId,invAmt) values (101,100);    -- 2
insert invoice (custId,invAmt) values (101,40);     -- 3
insert invoice (custId,invAmt) values (101,20);     -- 4
insert invoice (custId,invAmt) values (201,100);    -- 5

truncate table payment;
insert payment (invId,amt) values (1,10);   -- inv 1 pymt
insert payment (invId,amt) values (1,20);   -- inv 1 pymt
insert payment (invId,amt) values (1,30);   -- inv 1 pymt
insert payment (invId,amt) values (2,30);   -- inv 2 pymt
insert payment (invId,amt) values (2,70);   -- inv 2 pymt, now paid in full

insert payment (invId,amt) values (3,99);   -- inv 3 Overpayment
select i.invId,i.invAmt,ifnull(sum(p.amt),0) as paid,i.invAmt-ifnull(sum(p.amt),0) as due
from invoice i
left join payment p
on p.invId=i.invId
where i.custId=101
group by i.invId
order by i.invId
select i.invId,i.invAmt,ifnull(sum(p.amt),0) as paid,i.invAmt-ifnull(sum(p.amt),0) as due
from invoice i
left join payment p
on p.invId=i.invId
where i.custId=101
group by i.invId
having due>0
order by i.invId
+-------+---------+-------+---------+
| invId | invAmt  | paid  | due     |
+-------+---------+-------+---------+
|     1 | 9999.00 | 60.00 | 9939.00 |
|     4 |   20.00 |  0.00 |   20.00 |
+-------+---------+-------+---------+
select i.invId,i.invAmt,ifnull(sum(p.amt),0) as paid,i.invAmt-ifnull(sum(p.amt),0) as due
from invoice i
left join payment p
on p.invId=i.invId
where i.custId=101
group by i.invId
having due=0
order by i.invId
+-------+--------+--------+------+
| invId | invAmt | paid   | due  |
+-------+--------+--------+------+
|     2 | 100.00 | 100.00 | 0.00 |
+-------+--------+--------+------+
select i.invId,i.invAmt,ifnull(sum(p.amt),0) as paid,i.invAmt-ifnull(sum(p.amt),0) as due
from invoice i
left join payment p
on p.invId=i.invId
where i.custId=101
group by i.invId
having due<0
order by i.invId