Здравствуйте, elmal, Вы писали:
E>Есть следующая проблема. Есть одна достаточно большая таблица. Допустим Invoice. К ней соотношением 1 ко многим соединены другие таблицы, например Event и ServiceDistribution
Непонятно, что значит "1 ко многим". В примере почему-то приведено наоборот — "многие к одному", т.к. джойн идёт по primary key основной таблицы, а не по её foreign keys.
Если речь об обычной звезде, то известные мне оптимизаторы тупят с переупорядочиванием группировки и джойна. Точнее, неспособны понять суть primary key.
Давай я приведу более простой и понятный пример того, как переписываются star-join-aggregate запросы, может быть поможет и в этом случае:
-- 1: таблица
create table Invoices
(
id int identity primary key,
cityID int not null foreign key references city(id),
managerId int not null foreign key references manager(id),
amount numeric(10,4) not null
)
-- 2: наивный запрос:
select city.Name, manager.Name, sum(i.amount) as totals
from Invoices i
inner join city on city.id = i.cityId
inner join manager on manager.id = i.managerId
group by city.Name, manager.Name order by city.Name, manager.Name
-- 3: нормальный запрос
select city.Name, manager.Name, Totals
from (select cityId, managerId, sum(i.amount) as Totals from Invoices i group by cityId, managerId) i -- выполняем группировку по интересующим нас foreign keys
inner join city on city.id = i.cityId
inner join manager on manager.id = i.managerId
order by city.Name, manager.Name
Между этими запросами есть разница — она проявляется при наличии "однофамильцев". Но, во-первых, это легко исправить, выполнив группировку ещё раз во внешнем запросе — там обычно result set уже на порядок меньше, и это почти ничего не стоит. Во-вторых, зачастую нам именно это и надо, и исходный запрос выглядит примерно так (ох, сколько я такого кода переписал в своё время за индусами...):
select city.ID, city.Name, manager.ID, manager.Name, sum(i.amount) as totals
from Invoices i
inner join city on city.id = i.cityId
inner join manager on manager.id = i.managerId
group by CityId, city.Name, manager.ID, manager.Name
order by city.Name, manager.Name
Вот тут бы как раз оптимизатору сообразить, что у нас группировка по любому атрибуту после первичного ключа уже ничего не сгруппирует, и что можно безопасно переставлять джойн наружу group by...
Уыы, увы и ах. Проносите группировку внутрь руками.