Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Узкое место отчёта  [new]
НовыйЯ
Member

Откуда:
Сообщений: 193
Есть дома.
В домах есть объекты недвижимости разных типов: квартиры/офисы.
Есть история цен на эти объекты.

Отчёт строится по домам и показывает сравнение цен на объекты недвижимости разных типов на две заданные (входными параметрами) даты.

Запрос в реале посложне: дома предварительно отбираются с кучей усоловий, типов объектов больше, а история учитывается только активная, но узкое место - это пересечение с историей, которую приходится дублировать для двух дат с разносом цен по типам объектов.

Можно ли как-то схитрить или с другой стороны подойти, чтоб оно пошустрее бегало?
Пивоты не факт что рояль сыграют, наверное...
--- Входные параметры
declare @start_date datetime, @end_date datetime

--- Дома
declare @houses table
(
	house_id int,
	house_name varchar(100)
)

--- Объекты
declare @objects table 
(
	obj_id int,
	house_id int,
	obj_type varchar(7) ----  тип: "flat"/"office"	
)

--- История реализации (интервалы дат НЕ пересекаются!)
declare @history table
(
	obj_id  int,
	date_from datetime,
	dateto datetime,
	price money
)

---======Результат: 
----- сравнительный отчёт по каждому дому о суммарных цен 
----- его объектов различных типов на начальную и конечную дату

---- Наименование дома |  Сумма цен на начало периода | Сумма цен на конец периода 
----                   |       flat     |    office   |     flat     |    office   |

;with 
d1 as
(
	select h.obj_id, h.price
	from @history h
	where @start_date between h.date_from and h.dateto
),
d2 as
(
	select h.obj_id, h.price
	from @history h
	where @end_date between h.date_from and h.dateto	
)
select 
             h.house_name,
	price_flat_start = sum(case when o.obj_type = 'flat' then d1.price else 0 end),
	price_office_start = sum(case when o.obj_type = 'office' then d1.price else 0 end),
	price_flat_end = sum(case when o.obj_type = 'flat' then d2.price else 0 end),
	price_office_end = sum(case when o.obj_type = 'office' then d2.price else 0 end)
from
	@objects o
	inner join d1 on o.obj_id = d1.obj_id
	inner join d2 on o.obj_id = d2.obj_id
	inner join @houses h on o.house_id = h.house_id
group by h.house_name
28 ноя 12, 14:40    [13543140]     Ответить | Цитировать Сообщить модератору
 Re: Узкое место отчёта  [new]
НовыйЯ
Member

Откуда:
Сообщений: 193
Кстати, я не прав насчёт inner join.
Если всё в один запрос пихать, без заведения промежуточной таблицы и последовательного update её полей значениями из join'а c каждой отдельной историей, то нужен таки left join :(
28 ноя 12, 15:22    [13543510]     Ответить | Цитировать Сообщить модератору
 Re: Узкое место отчёта  [new]
dalex1973
Member

Откуда: Польша
Сообщений: 287
НовыйЯ
Кстати, я не прав насчёт inner join.
Если всё в один запрос пихать, без заведения промежуточной таблицы и последовательного update её полей значениями из join'а c каждой отдельной историей, то нужен таки left join :(

Зато можно индексы на таблицы навешать (кстати, Вы индексы смотрели?)
Попробуйте заменить таблицы-пeременные заменить на временные таблицы (#houses) с индексами. Иногда помогает.
Или: дайте ключи на @houses,@objects,@history
28 ноя 12, 15:33    [13543624]     Ответить | Цитировать Сообщить модератору
 Re: Узкое место отчёта  [new]
Добрый Э - Эх
Guest
Приведи тестовый набор репрезентативных данных (в виде СТЕ, а не через declare/create) и желаемый вид результата. А то на пустых табличках "хитрить и заходить с другой стороны" - не интересно...
28 ноя 12, 15:46    [13543789]     Ответить | Цитировать Сообщить модератору
 Re: Узкое место отчёта  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
НовыйЯ
Можно ли как-то схитрить или с другой стороны подойти, чтоб оно пошустрее бегало?
А оно медленно бегает? Пример пожалуйста, с реальным планом выполнения.
29 ноя 12, 03:10    [13547030]     Ответить | Цитировать Сообщить модератору
 Re: Узкое место отчёта  [new]
НовыйЯ
Member

Откуда:
Сообщений: 193
dalex1973
НовыйЯ
Кстати, я не прав насчёт inner join.
Если всё в один запрос пихать, без заведения промежуточной таблицы и последовательного update её полей значениями из join'а c каждой отдельной историей, то нужен таки left join :(

Зато можно индексы на таблицы навешать (кстати, Вы индексы смотрели?)
Попробуйте заменить таблицы-пeременные заменить на временные таблицы (#houses) с индексами. Иногда помогает.
Или: дайте ключи на @houses,@objects,@history

Насчёт индексирования исходных таблиц - это едва ли.
Они генерятся Dynamics CRM'ом, а точнее, EntityFramework'ом, который в нём используется.
Там свои правила, в которые вроде как не рекомендуется влезать простым смертным.

В @houses в итоге записывается относительно небольшой надор, и поэтому я решил использовать переменную, но Вы правы, # с индексом попробовать всё-таки стоит.

а @history - это, к сожалению, реальная физическая таблица, а не временный набор, и с ней уже ничего не сделаешь.((
29 ноя 12, 11:12    [13547794]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить