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

Откуда:
Сообщений: 1
Здравствуйте! Возможно опытные разработчики встречались с такой задачей и могут подсказать решение задачи.

Есть таблица в которой заданы значение параметра(тариф) с рамками его актуальности:
Company | Value | PeriodFrom | ReriodTo | LastUpdateTime

В поле LastUpdateTime хранится дата последнего обновления строки.
Периоды могут пересекаться всевозможными способами, могут быть "дырки" с отсутствующими значениями для Val. Значения Val почасовые. Необходимо выбрать все самые актуальные(с максимально LastUpdateTime) Val для всех часов в имеющихся периодах. Если значение в смежных периодах не меняется, то периоды необходимо объединить(необязательно).

Пока в голову пришло только такое решение: сделать таблицу с почасовыми датами с наименьшей, имеющейся в исходной таблице, до максимальной. Далее такой запрос:

FROM DENSE_RANK() OVER(PARTITION BY VAL ORDER BY dtHour, VAL)
         , * 
FROM 
    (
     SELECT * 
     FROM
             (
              SELECT  tblHours.*
                           ,  MAX(LASTUPDATEDATETIME) OVER (PARTITION BY Company, dtHour) AS maxDateRow
                           , ROW_NUMBER() OVER(PARTITION BY Company
                           , dtHour ORDER BY  dtHour,LASTUPDATEDATETIME) AS RN
                           , OO.*
              FROM tblHours
              LEFT JOIN tblPeriods cte OO ON dtHour BETWEEN OO.PERIODFROM AND OO.PERIODTO
             ) AS tmp
    WHERE tmp.LASTUPDATEDATETIME = tmp.maxDateRow
    ) ttt
ORDER BY intHour


Для одной компании работает около 30 секунд. Проблема, что в таблице порядка 30000 компаний, запрос просто отваливается(
16 апр 19, 09:05    [21863246]     Ответить | Цитировать Сообщить модератору
 Re: Выбрать актуальные значения из множества периодов.  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 30759
Roman7in
Необходимо выбрать все самые актуальные(с максимально LastUpdateTime) Val для всех часов в имеющихся периодах.
Можно написать так:
SELECT * 
FROM (
	SELECT  h.*
			, p.*
			, ROW_NUMBER() OVER(PARTITION BY p.Company, h.dtHour ORDER BY p.LASTUPDATEDATETIME DESC) AS RN
	FROM tblHours h
		LEFT JOIN tblPeriods p 
			ON h.dtHour BETWEEN p.PERIODFROM AND p.PERIODTO
	) AS tmp
WHERE RN = 1
А по скорости - нужно смотреть план запроса, индексы у таблиц.
И это, алиасы проставляйте везде, а не у некоторых таблиц и полей, читать будет проще.
16 апр 19, 09:51    [21863292]     Ответить | Цитировать Сообщить модератору
 Re: Выбрать актуальные значения из множества периодов.  [new]
dklim.kzn
Member

Откуда: Казань
Сообщений: 123
>> Если значение в смежных периодах не меняется, то периоды необходимо объединить(необязательно).

видел про упаковку периодов, это такая себе тема
https://www.osp.ru/winitpro/2015/10/13047177/
https://www.osp.ru/winitpro/2014/02/13039447/
курить и курить, если надо

по самой задаче можно смотреть еще на оконки FIRST_VALUE/LAST_VALUE
если критична скорость, то имеет смысл или индекс построить соответствующий
очень быстро шуршат оконки в таблицах columstore, прям вот отдельно хотел тему запилить)
10м с какими-то жуткими вязками самой на себя - миллисекунды на бытовом i7 с 17ым сервером
когда первая версия запроса работает 10 минут - это прям замечательно видеть после допиливания)

с не-columstore таблицами можно выкружить batch mode, подвязав фиктивным left join on 1=0 хоть пустую columstore-таблицу
http://sqlcom.ru/optimization_query/batch-mode-and-hacks-for-rowstore-queries-in-sql-server/
17 апр 19, 10:09    [21864511]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить