无需读取整个表格即可包含聚合数据的最佳方法

时间:2013-05-30 16:05:49

标签: mysql sql performance aggregates

我构建了一个查询,该查询使用典型的表头/详细信息表集来报告头表中的记录,但是在详细信息表上提供了各种类型的每个头记录的聚合数据。

为了解决分组问题,我创建了一个加入的视图,根据发票密钥进行所有聚合。

CREATE OR REPLACE VIEW TransactDetailSummary_V AS
  SELECT
td.invoice
, SUM(CASE WHEN td.TaxCollected1 + td.TaxCollected2 + td.TaxCollected3 <> 0 AND td.Type NOT IN (9,13) THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) as taxable_sales
, SUM(CASE WHEN td.TaxCollected1 + td.TaxCollected2 + td.TaxCollected3 = 0 AND td.Type NOT IN (9,13) THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) as nontaxable_sales
, SUM(CASE WHEN td.Type IN (8,18) THEN td.Amount ELSE 0 END) as total_taxes
, SUM(CASE WHEN td.Type IN (15,16,26) THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) AS returns
, SUM(CASE WHEN td.Type IN (24) THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) AS trade_ins
, SUM(CASE WHEN td.Type IN (9,13,22) THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) AS payments
, SUM(CASE WHEN td.Type = 2 THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) as part_sales
, SUM(CASE WHEN td.Type = 3 THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) as serial_sales
, SUM(CASE WHEN td.Type = 15 THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) as part_returns
, SUM(CASE WHEN td.Type = 16 THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) as serial_returns
, SUM(CASE WHEN td.Type = 10 THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) as misc_charges
, SUM(CASE WHEN td.Type = 6 THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) as labor_charges
, SUM(CASE WHEN td.Type IN (4,5,11) THEN ROUND(td.Quantity * td.Amount, 2) ELSE 0 END) as rental_sales
FROM transactdetail td
GROUP BY td.Invoice;

然后在报告查询中,我使用发票密钥加入详细信息视图。

SELECT
  'Customer Invoices COMPLETED' as section_title
  , CAST(th.Invoice as UNSIGNED) as Invoice
  , th.DateInvoice as invoice_date
  , th.DateApply as completed_date
  , th.orderstatus as status
  , th.customername as customer_name
  , tdv.taxable_sales
  , tdv.nontaxable_sales
  , tdv.total_taxes
  , tdv.returns
  , tdv.trade_ins
  , tdv.payments
  , tdv.part_sales
  , tdv.serial_sales
  , tdv.part_returns
  , tdv.serial_returns
  , tdv.misc_charges
  , tdv.labor_charges
  , tdv.rental_sales
FROM transactheader th
JOIN TransactDetailSummary_V tdv ON tdv.Invoice = th.Invoice
WHERE th.DateApply BETWEEN '2013-04-15' AND '2013-04-15'
  AND th.OrderStatus IN ('Complete','Backorder')
  AND th.Type = 1
  AND th.Created = 'invoice'
ORDER BY 1;

在这个例子中,我得到了13个带有聚合数据的头记录,很酷!但是我开始深入研究引擎的工作量,我发现了一些令人吃惊的事情。

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY <derived2>  ALL                 75609   
1   PRIMARY th  ref Invoice_Key,Type_Key,Status_Key Invoice_Key 20  tdv.invoice,const   10  Using where
2   DERIVED td  ALL                 350477  Using temporary; Using filesort

说明显示详细信息表中正在读取每一行,以便为我关心的13个标头提供聚合。我知道视图正在实现,然后根据连接进行过滤。

问题是,有没有办法做到这一点,它只能读取我关心的13张发票的详细信息?我对连接的子查询进行成像会以相同的方式工作,除非我可以将它关联起来吗?

提前感谢您的帮助。

0 个答案:

没有答案