这个选择子查询是否可以避免?

时间:2017-02-10 15:53:25

标签: mysql subquery

我在mysql中有两个表(发票和税金):

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

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

我试图回复像这样的报告

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)(如果包含税款则为regardess) 并指明该总金额的哪一部分应征税(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的{​​{1}}子查询,因此它非常慢。 我不能通过税名和费率将total_amountLEFT JOIN taxes组作为SUM(gross_amount)组,我需要显示每个国家/地区收集的总金额,无论金额是否已征税。有更快的替代方案吗?

1 个答案:

答案 0 :(得分:0)

我不知道使用此查询的确切用例,但问题是您尝试构建数据库的方式,您试图一次性获取整个数据。

理想情况下,您应该运行您拥有的查询并将其存储在另一个表(摘要表)中,然后根据需要直接从摘要表中进行查询。如果您在Invoices表中有新条目,那么您可以使用该查询在每个条目上运行,或通过cronjob定期更新汇总表。