Я склонен использовать то, что я называю TDQD - Test-Driven Query Design.Я строю сложный запрос шаг за шагом.Вы дали мне быстрый старт со своим основным запросом и подзапросом, который необходимо интегрировать в основной запрос.Разработка отдельного подзапроса - это именно то, что поощряет TDQD.
Задавая вопросы о SO, убедитесь, что вы минимизируете количество полей в таких вещах, как запросы.Например, четыре элемента product.weight_qty
, product.cubic_qty
, product.area_qty
, product.length_qty
, несомненно, все важны в вашем запросе «в реальной жизни», но они действительно не влияют на нас в SO.Одного из них здесь много;может быть, это даже излишне, так как вы выбрали desc_text
из product
.
Также важно предоставить схематическую схему таблиц - мой TDQD не управляется тестом, потому что вы не предоставили пригодный для использования,минимальные схемы таблиц, не говоря уже о выборке данных для обработки и ожидаемого результата.Вы получите лучшие ответы на свой вопрос, если на ваш вопрос будет легче ответить, потому что вы предоставили эту информацию.
Как общее практическое правило, в текущем тысячелетии не следует использовать FROM table1, table2, table3, …
нотация в SQL больше.Вы должны явно использовать JOIN.
Шаг 1 - Упрощение основного запроса и использование JOIN
Взяв ваш основной запрос, я изменил его следующим образом:
SELECT 'Labour' AS part_type,
ll.order_num,
oh.order_date,
lh.alloc_entry_date,
ll.part_code,
pr.desc_text,
oh.cust_code,
0 unit_rate_amt,
ll.order_qty,
ll.uom_code,
pr.length_qty
FROM ordhead AS oh
JOIN labourline AS ll ON oh.order_num = ll.order_num AND oh.cmpy_code = ll.cmpy_code
JOIN labourhead AS lh ON lh.order_num = ll.order_num AND lh.cmpy_code = ll.cmpy_code
JOIN product AS pr ON pr.part_code = ll.part_code AND pr.cmpy_code = pr.cmpy_code
WHERE ll.cmpy_code = 'EC'
AND pr.cmpy_code = 'EC'
AND oh.cmpy_code = 'EC'
AND lh.cmpy_code = 'EC'
AND oh.order_date >= MDY(08,01,2018)
AND oh.order_date < MDY(08,01,2019)
Iиспользуйте AS
, чтобы ввести сокращения для таблиц.Я часто использую однобуквенные сокращения;здесь двухбуквенные казались более подходящими.Я исключил ряд элементов из списка выбора как недостаточно существенный для вашего вопроса.
Из вашего повторного использования xyz.cmpy_code = 'EC'
я заключил, что таблицы могут быть объединены с cmpy_code
как частьусловие соединения;Я использую это в ON
условиях для соединений.Я также сделал вывод, что labourline
является центральной таблицей в этом запросе и перечислил его первым.Другие таблицы присоединяются к нему, а не друг к другу.Я оставил в запросе повторяющиеся условия, такие как AND pr.cmpy_code = 'EC'
, но, вероятно, я бы исключил все, кроме ll.cmpy_code = 'EC'
, если только планы запросов не продемонстрировали существенную выгоду от сохранения постоянных терминов.query
Это требует некоторой интерпретации вашего «рабочего подзапроса».Я предполагаю, что то, что вы называете CheckDate
, является labourline.alloc_entry_date
, а код детали - labourline.part_code
.С помощью нотации JOIN легко вставить подзапрос в основной запрос, например:
SELECT 'Labour' AS part_type,
ll.order_num,
oh.order_date,
lh.alloc_entry_date,
ll.part_code,
pr.desc_text,
oh.cust_code,
lr.unit_rate_amt,
ll.order_qty,
ll.uom_code,
pr.length_qty
FROM labourline AS ll
JOIN ordhead AS oh ON oh.order_num = ll.order_num AND oh.cmpy_code = ll.cmpy_code
JOIN labourhead AS lh ON lh.order_num = ll.order_num AND lh.cmpy_code = ll.cmpy_code
JOIN product AS pr ON pr.part_code = ll.part_code AND pr.cmpy_code = ll.cmpy_code
JOIN (SELECT lr1.part_code, lr1.unit_rate_amt AS unit_rate_amt
FROM labourates AS lr1
WHERE lr1.part_code = ll.part_code
AND lr1.effective_date =
(SELECT MAX(effective_date)
FROM labourates AS lr2
WHERE lr2.part_code = ll.part_code
AND lr2.effective_date <= ll.alloca_entry_date
)
) AS lr ON lr.part_code = ll.part_code
WHERE ll.cmpy_code = 'EC'
AND oh.order_date >= MDY(08,01,2018)
AND oh.order_date < MDY(08,01,2019)
Это коррелированный подзапрос из-за ссылок на ll.part_code
и ll.alloc_entry_date
в подзапросе.Я подозреваю, что были бы способы преобразовать это из коррелированного подзапроса в некоррелированный подзапрос.Конечно, если / когда это вызывает проблемы с медленным временем отклика, это первое место, где я бы искал улучшения.Однако значение ll.alloc_entry_date
имеет решающее значение для подзапроса, поэтому корреляция может быть неизбежной.Если корреляция неизбежна, то обеспечение наличия соответствующих индексов также становится критически важным.Даже основной запрос с объединениями на cmpy_code
и другими столбцами получит выгоду от доступности соответствующих индексов.