2017-02-10 10 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 

Я пытаюсь retrive отчет, как этот

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 

Идея в том, что счет-фактура имеет отношение has_many с налогами. Таким образом, счет-фактура может иметь или нет налоги. В отчете должна быть указана общая сумма (total_amount) для данной страны (учитывается если она включает налоги) и указать, какая часть этой общей суммы облагается налогом (taxable_amount) за конкретный налог.

Мой текущий подход это один:

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 

Ну, это работает, но для реальных данных (тысячи записей), это очень медленно, как select подзапрос для извлечения total_amount бежится для каждой строки Отчет. Я не могу сделать LEFT JOIN taxes с прямым SUM(gross_amount) как группы GROUP BY по налоговому названию и курсу, и мне нужно показать общее количество собранных за страну независимо от того, была ли налогооблагаемая сумма или нет. Есть ли более быстрая альтернатива этому?

ответ

0

Я не знаю конкретного варианта использования этого запроса, но проблема в том, как вы пытаетесь структурировать БД, вы пытаетесь получить все данные за один раз.

В идеале вы должны запустить запрос, который у вас есть, и сохранить его в другой таблице (сводная таблица), а затем запросить непосредственно из сводной таблицы, когда захотите. И если у вас есть новая запись в таблице Invoices, вы можете использовать запрос для запуска либо на каждой записи, либо периодически обновлять сводную таблицу через cronjob.

+1

Спасибо за ответ. Да, идеальный случай будет иметь таблицу с уже сохраненным отчетом, действующим как кеш. Этот запрос необходим для создания отчета в первый раз, поэтому я могу иметь таблицу отчетов, заполненную данными для работы с предстоящими заданиями cron. – John

+0

@John тогда не должно быть никаких проблем, если запрос занял несколько секунд дольше. Это так, как есть! –