Вы можете обнаружить, что это быстрее:
select c.cust_id,
(select sum(p.cost)
from purchases p
where p.cust_id = c.cust_id and
p.purchase_time >= '2018-01-01' and
p.purchase_time < '2019-01-01' and
) as total_cost
from customers c
having total_cost is not null;
Тогда это может использовать индекс для purchases(cust_id, purchase_time, cost)
. Только индекс необходим для расчета суммы. Это экономия. Что еще более важно, нет общих агрегаций - и это может быть большая экономия, которая компенсирует выполнение расчета для всех клиентов.
Однако, с тем же индексом, это может быть немного лучше:
select c.cust_id,
(select sum(p.cost)
from purchases p
where p.cust_id = c.cust_id and
p.purchase_time >= '2018-01-01' and
p.purchase_time < '2019-01-01'
) as total_cost
from customers c
where exists (select 1
from purchases p
where p.cust_id = c.cust_id and
p.purchase_time >= '2018-01-01' and
p.purchase_time < '2019-01-01'
);
РЕДАКТИРОВАТЬ:
Единственный способ реализовать то, что вы хотите, это явно включить столбец накопленной суммы в данные. Это потребовало бы перефразирования запроса (для выполнения требуемого вычитания) и наличия триггеров для сохранения значения.
Если исторические данные никогда не изменяются, это может быть разумным подходом. Однако обновления или вставки более ранних строк могут стать довольно дорогими.