【问题标题】:MySQL: Showing only orders that have a balance due when there are multiple bill tables for each order (and multiple payments)MySQL:当每个订单(和多个付款)有多个账单表时,仅显示有余额到期的订单
【发布时间】:2016-07-12 16:26:15
【问题描述】:

我的目标是获得一个(相对高效的)MySQL 视图,该视图显示所有仍有未结余额的订单——显示发票金额、所有存储费用的总和、支付的总金额以及每个订单的到期总额。这两个“账单”是orders表中的原始发票金额,然后是存储表中所有存储金额(费用)的总和。

订单表中有发票金额,支付表中有特定订单的所有付款,存储表中有特定订单的所有额外存储费用(支付和存储表与order_id上的订单表相关)字段)。

下面是我的架构示例数据(如果有帮助,这里是SQL fiddle):


CREATE TABLE orders
(
order_id int NOT NULL AUTO_INCREMENT,
invoice decimal(10,2),
PRIMARY KEY (order_id)
);


CREATE TABLE payments
(
payments_id int NOT NULL AUTO_INCREMENT,
order_id int,
amount decimal(10,2),
PRIMARY KEY (payments_id)
);

CREATE TABLE storage
(
storage_id int NOT NULL AUTO_INCREMENT,
order_id int,
amount decimal(10,2),
PRIMARY KEY (storage_id)
);


INSERT INTO orders (invoice)
VALUES ('250'), (NULL), ('150'), ('175.00'), ('175.00'), (NULL);

INSERT INTO payments (order_id, amount)
VALUES ('1', '50'), ('3', '50'), ('1', '100'), ('1', '150'), ('4', '100'), ('4', '25'), ('3', '50');

INSERT INTO storage (order_id, amount)
VALUES ('1', '50'), ('4', '25');

以下查询有效,但因为我重复了很多次并且看起来总共有 5 个子查询,我猜这不是让它工作的有效方法:


CREATE VIEW accounts_receivable AS
SELECT
orders.order_id AS orderid,
orders.invoice,
(SELECT sum(amount) from storage WHERE storage.order_id = orders.order_id) AS storagebill,
coalesce(sum(payments.amount), 0) AS paid,
coalesce(orders.invoice, 0) + (SELECT coalesce(SUM(storage.amount), 0) FROM storage WHERE storage.order_id = orders.order_id) - (SELECT coalesce(sum(payments.amount), 0) FROM payments WHERE orders.order_id = payments.order_id) AS due
FROM orders
LEFT JOIN payments on payments.order_id = orders.order_id
WHERE
(coalesce(orders.invoice, 0) + (SELECT coalesce(SUM(storage.amount), 0) FROM storage WHERE storage.order_id = orders.order_id) - (SELECT coalesce(sum(payments.amount), 0) FROM payments WHERE orders.order_id = payments.order_id)) > 0
GROUP BY orders.order_id

有什么方法可以更有效地获取这些数据?我猜这里有一些不同的方法可以加入数据,但我已经尝试(并寻找答案)无济于事。我对 SQL 比较陌生。

【问题讨论】:

  • 我认为您在最后一个 where 子句中省略了比较运算符。
  • 如果每个订单有“多张账单”——不应该有账单表吗,或者这就是存储费?我读得越多,我就越认为有更好的方法来处理模式 - 但也许我错了
  • @MageeWorld 是的,存储表是另一个“账单”表。我试图尽可能地总结标题,但也许它不太准确。但想法是,他们必须同时支付发票和随着时间累积的任何仓储费,并且这些费用都应计入已付金额和到期金额(以及 WHERE 条款)。它们是我的桌子,所以如果这样更有意义的话,我可以更换桌子。
  • @lrb 是的,关于需要运算符“> 0”的 WHERE 子句是正确的。不知何故,当我简化查询时,它并没有出现,但我现在已经改变了它。谢谢!
  • 理想情况下,您的设计应该生成一个简单的订单项金额汇总,订单或发票与相应的付款金额相连接,这样,付款金额的正数总和是尚未收取的金额,负数表示支付的款项(退还)。 order_id 6 怎么可能没有付款、发票金额或存储?它是未来购买的占位符吗?如果是这样,那可能很糟糕。

标签: mysql sql join left-join


【解决方案1】:

很抱歉重新格式化。我在质疑存储表以及为什么发票没有分成更小的部分。但是,我不知道细节,也许这是件好事 :) 这是一个有效的查询,可以为您提供类似的结果,但更具可读性。

SELECT
    * 
FROM
(
    SELECT 
        orderid,
        invoice,
        storage,
        totaldue=invoice+storage,
        totalpaid=paid,
        amountdue=(invoice+storage)-paid
    FROM
    (
            SELECT
                orderid=orders.order_id,
                invoice=orders.invoice,
                storage=
                (
                    SELECT SUM(amount) FROM storage where order_id=orders.order_id
                ),
                paid=SUM(payments.amount)   
            FROM
                orders
                LEFT OUTER JOIN payments on payments.order_id=orders.order_id                       
            GROUP BY
                orders.order_id,orders.invoice
    )AS DETAIL  
)AS SUMMARY
WHERE
    SUMMARY.amountdue>0

【讨论】:

  • 不幸的是,因为我必须从中创建一个 MySQL VIEW,MySQL 不允许我在“FROM”中放置子查询,所以我认为我不能使用上面的解决方案。另外,为了解决你所说的:你对模式的可疑性提出了一个很好的观点。不幸的是,还有一些其他的软件限制使得为所有“账单”设置一个表或者甚至将一个单独的发票表与一个单独的存储表一起存在问题。话虽如此,我真的很感谢你的帮助!
猜你喜欢
  • 2016-01-07
  • 1970-01-01
  • 1970-01-01
  • 2016-07-10
  • 1970-01-01
  • 2015-07-25
  • 2013-07-16
  • 1970-01-01
  • 2017-07-08
相关资源
最近更新 更多