SQL Server: упаковываем интервалы с приоритетами. Шаг 1. Продолжение
Во внешнем запросе оператор CROSS APPLY используется для определения нескольких результирующих столбцов. Результирующий столбец cs представляет количество активных интервалов непосредственно перед текущим событием начала, а столбец се представляет количество активных интервалов непосредственно после текущего события завершения. Столбец се вычисляется с помощью выражения: s — (se — s) — 1. В основе данного выражения лежит следующая логика: значение счетчика объединенных событий (se) за вычетом значения счетчика событий начала (s) показывает, сколько интервалов завершилось перед текущим событием начала. Если вычесть это значение из числа интервалов, начавшихся до текущего события начала, то вы получите число интервалов, активных в данной точке, вместе с текущим событием начала. Чтобы узнать, сколько интервалов было активно непосредственно перед текущим событием начала, достаточно вычесть 1. Точно так же, для вычисления се используется выражение (se — е) — е.
Внешний запрос фильтрует только события, отмечающие начало упакованного интервала (где cs = 0) или конец упакованного интервала (где cs = 0).

Оператор APPLY вычисляет другой столбец с именем ptybitval, который преобразует приоритет в двоичное значение в двоичном виде целого числа. В SQL Server для целых чисел используется двоичное дополненное представление для целого числа, где каждый разряд положительного целого числа (кроме крайнего левого разряда) представляет двоичное значение: POWER (2, — 1). Таким образом, с помощью выражения POWER (2, pty — 1) приоритет преобразуется в соответствующее двоичное значение. Затем это значение умножается на тип события, чтобы получить положительное двоичное значение для событий начала и отрицательное значение для событий завершения.
Далее внешний запрос в списке SELECT вычисляет столбец ptybitmap как нарастающий итог двоичных значений событий для пользователя в хронологическом порядке. Поэтому в каждой точке разряды, присутствующие в двоичном виде числа, отмечают активные приоритеты. Событие начала включает разряд, представляющий приоритет события, а событие завершения выключает его. Решение упаковывает интервалы с одним пользователем и приоритетом перед вычислением нарастающего итога, поэтому после упаковывания невозможно иметь два события одного вида в одно время. Вычисление нарастающего итога выполняется как агрегатная поразрядная операция OR.

Установленный разряд в крайней правой позиции двоичного представления числа указывает на самый высокий приоритет (помните, наименьшее число) среди активных. На следующем шаге будет показано, как изолировать этот разряд. Вы увидите, что из-за этой схемы на основе двоичного вида число приоритетов в вашем решении ограничено числом доступных разрядов в используемом типе данных (минус 1 с учетом неиспользуемого левого разряда). В моей таблице используется тип INT, поэтому максимальное число приоритетов — 31. Если вам требуется больше, используйте тип BIGINT, и число приоритетов увеличится до 63.