0

因此,我是幸运的人,能够为我们的应用程序优化查询,这对于我们获取的数据来说花费的时间太长了。我们正在寻找的数据并不复杂,但是糟糕的数据库设计使它变得比它应该的要困难得多(这很棒,因为我是大约一年前设计它的人)。

一般的想法是我们试图计算每个客户的总销售额(他们购买的东西增加了他们的余额)和总付款(他们根据余额支付了钱)。

表格:

顾客

  • ID
  • 公司

销售(发票)

  • ID
  • 客户ID

付款(account_payments)

  • ID
  • 客户ID
  • transaction_id(链接到 invoice_transactions)

交易(invoice_transactions)

  • ID
  • invoice_id(发票链接,如果付款则为空)
  • 数量

如果用户进行销售,则信息将记录在invoicesinvoice_transactions中,其中 invoice_transactions 的 invoice_id 包含包含 customer_id 的发票记录。

如果用户付款,则信息记录在account_paymentsinvoice_transactions中,其中 invoice_transaction 的 invoice_id 为 NULL,account_payments 包含 transaction_id 和 customer_id。

我知道,这太可怕了……我以为我很聪明!好吧,我仔细考虑了这个问题,并提出了一个不错的解决方案:

SELECT SQL_NO_CACHE
    c.company,
    (SELECT SUM(amount) FROM sales),
    (SELECT SUM(amount) FROM payments)
FROM customers c
JOIN invoices i ON i.customer_id = c.id
JOIN invoice_transactions sales ON i.invoice_id = sales.id
JOIN account_payments ap ON ap.customer_id = c.id
JOIN invoice_transactions payments ON ap.transaction_id = payments.id

除了给我一个错误“#1146 - 表 'db.sales' 不存在”之外,它什么都不做。我猜这与连接之前读取的子查询有关,但老实说我不知道​​。不幸的是,我不知道解决这个问题的另一种方法......如果有人能帮帮我,我将不胜感激!

4

2 回答 2

2

我认为最好的方法是将元素销售和付款分成子查询,您当前的方法是在进行聚合之前将所有付款与所有发票交叉连接。

SELECT  c.ID, 
        c.Company, 
        COALESCE(Sales.Amount, 0) AS Sales, 
        COALESCE(Payments.Amount, 0) AS Payments
FROM    Customers c
        LEFT JOIN
        (   SELECT  Customer_ID, SUM(Amount) AS Amount
            FROM    Invoices
                    INNER JOIN invoice_transactions
                        ON Invoice_ID = Invoices.ID
            GROUP BY Customer_ID
        ) As Sales
            ON Sales.Customer_ID = c.ID
        LEFT JOIN
        (   SELECT  Customer_ID, SUM(Amount) AS Amount
            FROM    Account_Payments 
                    INNER JOIN invoice_transactions tr
                        ON tr.ID = Transaction_ID
            GROUP BY Customer_ID
        ) AS Payments
            ON Payments.Customer_ID = c.ID;

这将包括没有发票和没有付款的客户。您可以将左连接更改为内连接以进行操作。

SQL Fiddle 上的工作示例

于 2012-06-19T16:09:38.493 回答
1

您的查询没有意义。

完成所有连接后,为什么不直接使用“from”子句中的表:

SELECT c.company, SUM(sales.amount),  SUM(payments.amount)
FROM customers c JOIN invoices i ON i.customer_id = c.id JOIN
     invoice_transactions sales ON i.invoice_id = sales.id JOIN
     account_payments ap ON ap.customer_id = c.id JOIN
     invoice_transactions payments ON ap.transaction_id = payments.id
group by c.company

仅仅在“from”子句中给表一个别名并不能使它在查询的其他地方的子查询中可用。

我还添加了一个 GROUP BY 子句,因为您的查询似乎是按公司汇总的。

于 2012-06-19T15:54:41.570 回答