2017-02-10 7 views
0

私は、MySQLに二つのテーブル(請求書や税金を)持っている:このサブクエリは回避できますか?

Invoices: 
    - id 
    - account_id 
    - issued_at 
    - total 
    - gross_amount 
    - country 

Taxes: 
    - id 
    - invoice_id 
    - tax_name 
    - tax_rate 
    - taxable_amount 
    - tax_amount 

私は請求書がhas_many関係を持っていることを、この背後にある考え方は、この

rep_month | country | total_amount | tax_name | tax_rate(%) | taxable_amount | tax_amount 
-------------------------------------------------------------------------------------- 
2017-01-01 | ES  | 1000   | TAX1  | 21   | 700   | 147 
2017-01-01 | ES  | 1000   | TAX2  | -15   | 700   | 105 
2016-12-01 | FR  | 100   | TAX4  | 20   | 30    | 6 
2016-12-01 | FR  | 100   | B2B  | 0   | 70    | 0 
2017-01-01 | GB  | 2500   | TAX3  | 20   | 1000   | 200 

ようなレポートをretriveしようとしています税金でしたがって、請求書には税金がある場合とない場合があります。レポートには、特定の国(税金が含まれているかどうかを問わず)に収集された合計金額(total_amount)と、その合計金額のどの部分が特定の税金に対して課税対象かを示す必要があります。

私の現在のアプローチはこの1つである:

まあ
SELECT 
DATE_FORMAT(invoices.issued_at, '%Y-%m-01') AS rep_month, 
invoices.country AS country 
(SELECT sum(docs.gross_amount) 
    FROM invoices AS docs 
    WHERE docs.country = invoices.country 
    AND DATE_FORMAT(docs.issue_date, '%Y-%m-01') = rep_month 
) AS total_amount, 
taxes.tax_name AS tax_name, 
taxes.tax_rate AS tax_rate, 
SUM(taxes.taxable_amount) AS taxable_amount, 
SUM(taxes.tax_amount) AS tax_amount 
FROM invoices 
JOIN taxes ON invoices.id = taxes.document_id 
AND documents.issue_date BETWEEN '2016-01-01' AND '2017-12-31' 
GROUP BY account_id, rep_month, country, tax_name, tax_rate 
ORDER BY country desc 

、これは動作しますが、total_amountを取得するためのselectサブクエリがそれぞれの行のためのもので実行されるよう、実際のデータセット(何千ものレコード)のために、それは本当に遅いですレポート。 LEFT JOIN taxesを直接SUM(gross_amount)としてGROUP BYグループにすることはできません。課税されるかどうかにかかわらず、国ごとに収集された合計を表示する必要があります。これに代わるより速い方法がありますか?

答えて

0

このクエリを使用する正確な使用例はわかりませんが、問題はDBを構造化しようとする方法で、データ全体を一度に取得しようとしています。

理想的には、持っているクエリを実行して別のテーブル(サマリーテーブル)に格納し、必要なときにいつでもサマリーテーブルから直接クエリを実行する必要があります。また、Invoicesテーブルに新しいエントリがある場合は、クエリを使用してすべてのエントリに対して実行するか、cronジョブでサマリテーブルを定期的に更新することができます。

+1

返信いただきありがとうございます。ええ、理想的なケースは、既にキャッシュとして動作するレポートが格納されたテーブルを持つことです。このクエリーは、初めてレポートを作成する場合には必要です。次回のcronジョブを処理するためのデータをレポート表に作成することができます。 – John

+0

@ジョンその後、クエリに数秒かかる場合は問題ありません。それは正しい方法です! –

関連する問題