0

したがって、取得するデータに時間がかかりすぎるアプリケーションのクエリを最適化できる幸運な人です。私たちが探しているデータはそれほど複雑ではありませんが、データベースの設計が安っぽいため、本来よりもはるかに困難になっています (これは素晴らしいことです。なぜなら、私が約 1 年前に設計したからです)。

一般的な考え方は、各顧客の総売上 (残高を増やす何かを購入する) と総支払い (残高に対してお金を支払った) を計算しようとしているということです。

テーブル:

お客様

  • ID
  • 会社

売上(請求書)

  • ID
  • 顧客ID

支払い (account_payments)

  • ID
  • 顧客ID
  • transaction_id (invoice_transactions へのリンク)

トランザクション (invoice_transactions)

  • ID
  • 請求書 ID (請求書へのリンク、支払いの場合は null)

ユーザーが販売を行った場合、情報は と に記録されinvoicesinvoice_transactionsinvoice_transactions は customer_id を含む送り状レコードの送り状 ID を持ちます。

ユーザーが支払いaccount_paymentsを行う場合、情報はとに記録されinvoice_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

最良のアプローチは、Sales 要素と Payments 要素をサブクエリに分割することだと思います。現在の方法は、集計を行う前に、すべての支払いとすべての請求書をクロス結合することです。

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 に答える