Лучший способ включить агрегированные данные без чтения всей таблицы
Я построил запрос, который использует типичный набор заголовков / подробных таблиц для отчета о записях из таблицы заголовков, но предоставляет агрегированные данные для каждой записи заголовка из различных типов в таблице подробностей.
Чтобы обойти проблемы с группировкой, я создал представление для объединения, которое выполняет всю агрегацию на основе ключа счета.
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 счетов, которые мне нужны? Я представляю себе объединенный подзапрос, который будет работать так же, если только я не смогу сопоставить его?
Заранее благодарю за любую помощь.