Я называю любой запрос, который создает данные, проблемой. SQL следует использовать только для запроса данных. Вам не нужны планы выполнения, если вы понимаете свой процесс и работу, которую он выполняет.
Сначала разделите ваш основной прогноз как шаг 1, либо на временную таблицу, либо на переменную таблицы, в зависимости от того, сколько записей у вас есть. , Кэширование каждого набора, который вам нужен в производственном запросе, позволяет вам измерять размер загрузки как счетчик выбора (*).
insert into @mytablevariable values
SELECT
a.col_a,
a.col_b,
a.col_c,
b.col_a,
b.col_b
-- build this column later
FROM a
INNER JOIN b ON a.x = b.x
Далее, кэшируйте результат этого вложенного запроса, чтобы внутреннее соединение не проводилось каждая итерация.
insert into @mysub values
SELECT a_sub.col_a
FROM a_sub
INNER JOIN b_sub
ON a_sub.x = b_sub.x
AND b.col_b <> b_sub.col_b
Мы специально создали отходы, чтобы справиться с ними, изменив @mysub в соответствии с вашими требованиями к обработке. Наша цель - исключить работу, выбрав правильные данные в правильном порядке.
В этом процессе больше всего выделяется предложение WHERE о том, что поле даты находится в пределах диапазона дат.
AND a.date > a_sub.date AND a.date <= DATEADD(d, 28, a_sub.date)
Естественно, таблицы не индексируются по значениям столбцов даты, и поэтому при этом сравнении WHERE должно выполняться полное сканирование таблицы, или то, что мы называем Extractor. Экстрактор извлекает часть (подмножество) данных из набора. Поскольку этот экстрактор находится в подзапросе, который выполняется для каждого результата внешней записи, как и любой другой вложенный процесс , вся таблица проверяется снова и снова. Мы всегда хотим минимизировать извлечение до одного прохода, что делается только тогда, когда мы заканчиваем sh организацию критериев на экстракторе. Никогда не вкладывайте экстракторы.
Во-первых, минимизируйте размер результатов экстрактора @mysub с помощью диапазона значений даты, необходимых во внешнем запросе @mytablevariable.
insert into @mysub values
SELECT a_sub.col_a
FROM a_sub
INNER JOIN b_sub
ON a_sub.x = b_sub.x
AND b.col_b <> b_sub.col_b
and a_sub.date <= DATEADD(d, 28, select min(a.date) from @mytablevariable)
and a_sub.date > (select max(a.date) from @mytablevariable)
Затем можно спроектировать @mysub. в ваш 21-дневный набор, и меньший набор снова для остальных. В оставшейся части предложения WHERE разверните @mysub столбцами, которые вы сравниваете. Чтобы создать конечный продукт, выберите все из первой таблицы и выполните один поиск для каждой записи следующим образом.
select
*,
case
when b.col_a in (select col_a from @mysub28) then 'Yes'
else 'No'
end as IsRepeat28,
case
when b.col_a in (select col_a from @mysub21) then 'Yes'
else 'No'
end as IsRepeat21
-- rinse, repeat
from
@mytablevariable
В любое время, когда у вас есть производственный процесс, выделите компоненты и работайте над критериями выбора экстракторов. поэтому они делают только один проход.