SQL Server: упаковываем интервалы с приоритетами. Шаг 4 и оптимизация решения с использованием APPLY
Содержание:
1. Постановка задачи;
2. Шаг 1 ;
3. Шаг 2, 3;
4. Шаг 4 и оптимизация решения с использованием APPLY (Вы читаете данный раздел).

Четвертый и последний шаг определяет обобщенное табличное выражение C4 (подходящее имя) во внешнем запросе из предыдущего шага (также известном как explosive query). Последний внешний запрос группирует строки из C4 по username, newpty и grp, и для каждой группы возвращает минимальное и максимальное время событий, как время начала и завершения результирующих интервалов. Вот внешний запрос:

Полное решение. Получили отличный от данного результат? Ищите проблему в программной части ПО вашего ПК - возможно, вам потребуется помощь компьютерного мастера (его вы найдете на www.mositservice.ru (http://www.mositservice.ru))
В коде выше приведен полный код решения. Выходные данные представлены в таблице ниже.
Для выполнения этого решения с большим набором тестовых данных (5000000 строк) на моем старом ноутбуке потребовалось 45 секунд. Это неплохо, но может быть и лучше.
Оптимизация решения с использованием APPLY
Хотя программный код в коде, представленном выше, создает вспомогательные индексы для нашего решения, существует несколько оконных функций с различными особенностями секционирования и упорядочения, поэтому нельзя обойтись без пары явных операторов сортировки в плане. Оператор сортировки масштабируется по формуле N Log N. Поэтому когда в оконных функциях присутствует элемент секционирования, можно повысить производительность с помощью метода, первоначально предложенного Адамом Махаником. Используйте оператор CROSS APPLY для таблицы, содержащей секции (Users в нашем случае), и примените запрос (или встроенную функцию, возвращающую табличное значение, которая инкапсулирует запрос) к разделу. Таким образом, одна большая операция будет разделена на несколько мелких, что в данном случае приведет к повышению производительности. В коде, представленном ниже, решение для одного пользователя инкапсулировано во встроенной функции, возвращающей табличное значение, с именем Packedlntervals.
1. Постановка задачи;
2. Шаг 1 ;
3. Шаг 2, 3;
4.

Четвертый и последний шаг определяет обобщенное табличное выражение C4 (подходящее имя) во внешнем запросе из предыдущего шага (также известном как explosive query). Последний внешний запрос группирует строки из C4 по username, newpty и grp, и для каждой группы возвращает минимальное и максимальное время событий, как время начала и завершения результирующих интервалов. Вот внешний запрос:
SELECT username, newpty AS pty, MIN (ts) AS starttime, MAX (ts) AS endtime
FROM C4
GROUP BY username, newpty, grp;Полное решение. Получили отличный от данного результат? Ищите проблему в программной части ПО вашего ПК - возможно, вам потребуется помощь компьютерного мастера (его вы найдете на www.mositservice.ru (http://www.mositservice.ru))
В коде выше приведен полный код решения. Выходные данные представлены в таблице ниже.
Для выполнения этого решения с большим набором тестовых данных (5000000 строк) на моем старом ноутбуке потребовалось 45 секунд. Это неплохо, но может быть и лучше.
Оптимизация решения с использованием APPLY
Хотя программный код в коде, представленном выше, создает вспомогательные индексы для нашего решения, существует несколько оконных функций с различными особенностями секционирования и упорядочения, поэтому нельзя обойтись без пары явных операторов сортировки в плане. Оператор сортировки масштабируется по формуле N Log N. Поэтому когда в оконных функциях присутствует элемент секционирования, можно повысить производительность с помощью метода, первоначально предложенного Адамом Махаником. Используйте оператор CROSS APPLY для таблицы, содержащей секции (Users в нашем случае), и примените запрос (или встроенную функцию, возвращающую табличное значение, которая инкапсулирует запрос) к разделу. Таким образом, одна большая операция будет разделена на несколько мелких, что в данном случае приведет к повышению производительности. В коде, представленном ниже, решение для одного пользователя инкапсулировано во встроенной функции, возвращающей табличное значение, с именем Packedlntervals.