Предполагая, что результирующий набор представляет собой небольшое подмножество заказов (скажем, менее 1% заказов, но 1% для иллюстрации), я бы сформулировал запрос следующим образом:
select o.*
from customers c join
orders o
on o.Customer_id = c.Customer_id and
o.StartDate between c.EarliestActiveOrder and c.LatestActiveOrder
where c.Location = 'New York' and c.industry = 'Finance';
Стратегия индексирования сложна. Для небольших наборов результатов вы, вероятно, захотите сначала ограничить клиентов, а затем найти соответствующие заказы. Этот подход предлагает индексы для:
customers(location, industry, customer_id, EarliestActiveOrder, LatestActiveOrder)
orders(customer_id, startdate)
Если бы у вас были другие столбцы для фильтрации, вам потребуются отдельные индексы дляих. Например, для industry
-только фильтрации:
customers(industry, customer_id, EarliestActiveOrder, LatestActiveOrder)
Это может стать громоздким.
Если, с другой стороны,ваш набор результатов, вероятно, будет значительным числом заказов, тогда сканирование таблицы orders
может быть более эффективным. Вы можете попробовать положиться на оптимизатор. Или просто нажмите его в правильном направлении, сформулировав запрос следующим образом:
select o.*
from orders o
where exists (select 1
from customers c
where o.Customer_id = c.Customer_id and
o.StartDate between c.EarliestActiveOrder and c.LatestActiveOrder and
c.Location = 'New York' and c.industry = 'Finance'
);
В этом случае вам нужен индекс на customers(customer_id)
- но это, вероятно, уже первичный ключ, так что вы в порядке. Преимущество в том, что вам не нужно беспокоиться о точных критериях фильтрации. Недостатком является полное сканирование таблицы на orders
(но не дополнительная работа для join
, group by
или order by
).