MySQL如何显示订单已付未付金额

How to display the paid and unpaid amount of Order in MySQL

客户TABLE

+------------+----------+-------+-------+-------------+-----------------------------+----------+--------------+
| CustomerID | Fname    | Mname | Lname | Contact_no  | Address                     | Valid_id | Credit_Limit |
+------------+----------+-------+-------+-------------+-----------------------------+----------+--------------+
|          7 | John     | Dale  | Doe   | 09123654789 | Asan Sur, Sison, Pangasinan | NULL     |     5000.000 |
|          8 | Jane     | Dale  | Doe   | 09987654123 | Asan Sur, Sison, Pangasinan | NULL     |     1500.000 |
|         91 | Kurdapya | Buang | Selos | 09741258963 | Paldit, Sison, Pangasinan   | NULL     |     5000.000 |
+------------+----------+-------+-------+-------------+-----------------------------+----------+--------------+

订单TABLE

+---------+------------+----------------+----------+------------+
| OrderID | CustomerID | DateOfPurchase | Discount | DueDate    |
+---------+------------+----------------+----------+------------+
|      82 |          7 | 2022-04-17     | 0        | 2022-05-17 |
|      83 |         91 | 2022-04-17     | 0        | 2022-05-17 |
|      84 |          8 | 2022-04-17     | 0        | 2022-05-17 |
|      85 |         91 | 2022-04-17     | 0        | 2022-05-17 |
|      86 |          7 | 2022-04-17     | 0        | 2022-05-17 |
|      87 |         91 | 2022-04-18     | 0        | 2022-05-18 |
|     109 |          7 | 2022-04-25     | 0        | 2022-05-25 |
+---------+------------+----------------+----------+------------+

付款TABLE

+-----------+------------+---------+------------+----------+
| PaymentID | CustomerID | OrderID | PayDate    | Amount   |
+-----------+------------+---------+------------+----------+
|        20 |          7 |      82 | 2022-04-25 |  800.000 |
|        21 |         91 |      83 | 2022-04-17 | 2500.000 |
|        22 |         91 |      85 | 2022-04-17 |  200.000 |
|        23 |         95 |      88 | 2022-04-18 | 2122.000 |
|        24 |         96 |      90 | 2022-04-25 |  577.000 |
|        25 |         97 |     111 | 2022-04-25 |    0.000 |
|        26 |         98 |     114 | 2022-04-25 |  166.000 |
|        27 |         99 |     115 | 2022-04-25 | 1740.000 |
+-----------+------------+---------+------------+----------+

订单详情TABLE

+-------+---------+-----------+------+
| OR_ID | OrderID | ProductID | QTY  |
+-------+---------+-----------+------+
|   173 |      82 |         5 |    1 |
|   174 |      82 |         9 |    1 |
|   184 |      86 |         5 |    1 |
|   185 |      86 |         9 |    1 |
|   186 |      86 |        13 |    1 |
|   187 |      86 |        17 |    1 |
|   224 |     109 |         3 |    3 |
|   225 |     109 |         6 |    3 |
|   292 |     145 |        20 |    2 |
|   293 |     145 |        12 |    1 |
|   294 |     145 |         8 |    2 |
|   295 |     146 |        14 |    1 |
|   296 |     146 |        11 |    1 |
|   297 |     146 |        12 |    1 |
|   298 |     146 |         3 |    1 |
|   299 |     146 |         6 |    1 |
|   300 |     146 |         7 |    1 |
|   301 |     146 |        16 |    1 |
+-------+---------+-----------+------+

我不知道是否需要,但这是我的 产品 TABLE:

+-----------+---------------+-----------------------+------------+-----------+------+
| ProductID | Pname         | Pdesc                 | PUnitPrice | weight    | Unit |
+-----------+---------------+-----------------------+------------+-----------+------+
|         2 | Pepsi         | 1 Case Glass Bottle   |    313.000 | 1 Litre   |   12 |
|         3 | Mountain Dew  | 1 Case Glass Bottle   |    231.000 | 750 ML    |   12 |
|         4 | Pepsi         | 1 Case Plastic Bottle |    620.000 | 1.5 Litre |   12 |
|         5 | Mirinda       | 1 Case Plastic Bottle |    620.000 | 1.5 Litre |   12 |
|         6 | Mountain Dew  | 1 Case Plastic Bottle |    620.000 | 1.5 Litre |   12 |
|         7 | Mountain Dew  | 1 Case Glass Bottle   |    145.000 | 8 oz      |   24 |
|         8 | Pepsi         | 1 Case Glass Bottle   |    145.000 | 8 oz      |   24 |
|         9 | Mirinda       | 1 Case Glass Bottle   |    145.000 | 8 oz      |   24 |
|        10 | 7up           | 1 Case Glass Bottle   |    145.000 | 8 oz      |   24 |
|        11 | Sting         | 1 Case Glass Bottle   |    266.000 | 240 ml    |   24 |
|        12 | Tropicana     | 1 Case Glass Bottle   |    266.000 | 240 ml    |   24 |
|        13 | Cobra         | 1 Case Glass Bottle   |    266.000 | 240 ml    |   24 |
|        14 | Sting         | 1 Case Plastic Bottle |    166.000 | 300 ml    |   12 |
|        15 | Cobra         | 1 Case Plastic Bottle |    166.000 | 300 ml    |   12 |
|        16 | Mountain Dew  | 1 Case Plastic Bottle |    135.000 | 295 ml    |   12 |
|        17 | Mirinda       | 1 Case Plastic Bottle |    135.000 | 295 ml    |   12 |
|        18 | Pepsi         | 1 Case Plastic Bottle |    135.000 | 295 ml    |   12 |
|        19 | Ginebra       | 1 Case Glass Bottle   |    129.000 | 350 ml    |   24 |
|        20 | San Mig Light | 1 Case Glass Bottle   |   1070.000 | 330 ml    |   24 |
|        21 | Red Horse     | 1 Case Glass Bottle   |    535.000 | 500 ml    |   12 |
|        22 | Red Horse     | 1 Case Glass Bottle   |    545.000 | 1 Litre   |    6 |
+-----------+---------------+-----------------------+------------+-----------+------+

我想发生什么

我只想在一行中显示customerID 7 的所有已付款订单和他的未付款订单。我不知道如何从查询开始。我应该使用 If() 条件吗?如何正确查询它以实现我想要的输出?

我想要的输出

+--------+------+-------+-------+-------+-------------+-----------------------------+--------------+----------+
| unpaid | paid | Fname | Mname | Lname | Contact_no  | Address                     | Credit_Limit | total    |
+--------+------+-------+-------+-------+-------------+-----------------------------+--------------+----------+
| 2995   | 6014 | John  | Dale  | Doe   | 09123654789 | Asan Sur, Sison, Pangasinan |     5000.000 | 9009.000 |
+--------+------+-------+-------+-------+-------------+-----------------------------+--------------+----------+

编辑

这就是我到目前为止尝试过的方法

第一次尝试: 我正在尝试计算未付款订单,这是 output:

select 
    if(py.Amount IS NULL, sum(od.QTY * p.PUnitPrice), CONCAT(py.Amount - sum(od.QTY * p.PUnitPrice))) as remarks, 
    c.Fname, c.Mname, c.Lname, c.Contact_no, c.Address, c.Credit_Limit, 
    sum(od.QTY * p.PUnitPrice) as total 
from customer c INNER JOIN orders r on r.CustomerID=c.CustomerID
INNER join order_details od on r.OrderID=od.OrderID 
INNER JOIN product p on od.ProductID = p.ProductID 
join payment py 
where c.CustomerID=7 

尝试 1 的结果:

+-------------+-------+-------+-------+-------------+-----------------------------+--------------+------------+
| remarks     | Fname | Mname | Lname | Contact_no  | Address                     | Credit_Limit | total      |
+-------------+-------+-------+-------+-------------+-----------------------------+--------------+------------+
| -134335.000 | John  | Dale  | Doe   | 09123654789 | Asan Sur, Sison, Pangasinan |     5000.000 | 135135.000 |
+-------------+-------+-------+-------+-------------+-----------------------------+--------------+------------+

第二次尝试:

SELECT IF(py.OrderID IS NULL, sum(od.QTY * p.PUnitPrice), 0) AS unpaid,
if(py.OrderID IS NOT NULL, sum(od.QTY * p.PUnitPrice), 0) as paid,
sum(od.QTY * p.PUnitPrice) as total,
O.OrderID, O.CustomerID, date_format(O.DateOfPurchase, '%M %d, %Y') AS DateOfPurchase, date_format(O.DueDate, '%M %d, %Y') AS DueDate
from Orders O INNER JOIN order_details od on od.OrderID=O.OrderID
INNER JOIN product p ON od.ProductID=p.ProductID
LEFT JOIN Payment py ON py.OrderID = O.OrderID
where O.CustomerID = 7
GROUP by O.OrderID
ORDER by O.OrderID desc

尝试 2 的结果:

+----------+----------+----------+---------+------------+----------------+--------------+
| unpaid   | paid     | total    | OrderID | CustomerID | DateOfPurchase | DueDate      |
+----------+----------+----------+---------+------------+----------------+--------------+
| 1829.000 |    0.000 | 1829.000 |     146 |          7 | April 27, 2022 | May 27, 2022 |
|    0.000 | 2696.000 | 2696.000 |     145 |          7 | April 27, 2022 | May 27, 2022 |
|    0.000 | 2553.000 | 2553.000 |     109 |          7 | April 25, 2022 | May 25, 2022 |
| 1166.000 |    0.000 | 1166.000 |      86 |          7 | April 17, 2022 | May 17, 2022 |
|    0.000 |  765.000 |  765.000 |      82 |          7 | April 17, 2022 | May 17, 2022 |
+----------+----------+----------+---------+------------+----------------+--------------+

注意:如何对已付和未付列中的所有行求和?

您接近解决方案的方式显然不起作用,因此您正在寻求帮助。您的第一个查询,您正在加入付款 table,但没有条件仅限于客户 7 的付款。这可能会巧合,因为只有一个付款记录。但是对于不止一个的客户, 您的总数将因笛卡尔积结果而发生偏差。

您应该做的是 pre-aggregate 购买与付款完全分开,这样您将最多拥有您正在寻找的一个客户的单一记录。现在,如果您想将结果应用到所有客户,那只会增加一点点,稍后会介绍。

每个单独,防止混淆多个杂乱。

在最短的时间里,由于您只关心购买和支付的总计,我不会关心每个订单的总计,只关心每个客户的总计。

select
        c.Fname, 
        c.Mname, 
        c.Lname, 
        c.Contact_no, 
        c.Address, 
        c.Credit_Limit, 
        coalesce( PQ_Orders.TotalOrders, 0 ) TotalOrders,
        coalesce( PQ_Payments.TotalPaid, 0 ) TotalPayments,
        coalesce( PQ_Orders.TotalOrders, 0 )
            - coalesce( PQ_Payments.TotalPaid, 0 ) BalanceDue
    from 
        customer c 
            LEFT JOIN
            ( select
                    o.customerID,
                    sum( od.qty * p.pUnitPrice ) TotalOrders
                from
                    orders o
                        join order_details od
                            on o.orderID = od.orderID
                            join product p
                                on od.productid = p.productid
                where
                    o.customerid = 7
                group by
                    o.customerID ) PQ_Orders
                on c.customerID = PQ_Orders.customerID
            LEFT JOIN
            ( select
                    py.customerid,
                    sum( py.Amount ) TotalPaid
                from
                    payments py
                where
                    py.customerid = 7
                group by
                    py.customerid ) PQ_Payments
                on c.customerID = PQ_Payments.CustomerID
    where 
        c.CustomerID = 7 

现在,如果您想要所有客户,只需删除所有 WHERE 子句,以便它获得所有客户。每个内部查询都将客户 ID 作为数据分组,因此如果一个人有 10 个订单和 3 个付款,您仍然有每个 PRE-QUERY (PQ) 聚合,每个客户只有 1 个订单条目和 1 个条目每个客户的付款。重新加入主要客户 table 并将其应用 across-the-board 给所有客户。

对O/P

的澄清

为了帮助澄清,让我们看看您的要求。对于单个客户,购买了多少东西。将其视为一个查询。根据订单详细信息和相应的产品价格获取该客户的所有订单,并按客户分组汇总。现在客户的 WHERE 子句 = 7 只是因为您是关于一个客户的。但是,如果没有 where 将向所有客户显示他们各自购买的所有商品。无论他们有 1 个订单还是 274 个订单,您最多(因为按客户 ID 分组)每个客户有 1 条记录。它是该客户的总计。

现在,付款的上下文完全相同。我不在乎他们购买了什么或何时购买。我只关心给定客户的付款。与购买说明中一样,有或没有客户 ID = 7 的 WHERE。同样,无论 1 笔还是 75 笔付款,每个客户只有 1 条记录,每个客户 1 条记录。

所以现在,您有一个 1:1:1 可能的比率,即 1 位客户对 1 次购买与可能的 1 次付款总额。

LEFT JOIN 的意思是,我想要左边的东西(客户),但可以选择性地在右边找到东西(购买 AND/OR 付款)。

因此 COALESCE() 可防止空值在计算中出错。如果给定 pre-query 的购买或付款有一个值,则获取它,否则,假设为零。因此,您可以只获取一个有问题的客户,或者通过删除 WHERE 子句,您可以获得所有客户的所有购买总额和所有付款总额,以获得所有客户的全部未结余额。