SQL Server: упаковываем интервалы с приоритетами. Шаг 2
Содержание:
1. Постановка задачи;
2. Шаг 1 ;
3. Шаг 2, 3 (Вы читаете данный раздел);
4. Шаг 4 и оптимизация решения с использованием APPLY.
Программный код, реализующий шаг 2, показан ниже, а выходные данные этого шага приведены в таблице, представленной также чуть ниже.
В программном коде определено обобщенное табличное выражение C3 на основе внешнего запроса из шага 1. Внешний запрос на шаге 2 направлен к СЗ и использует два оператора CROSS APPLY для вычисления нескольких столбцов результатов. Первый оператор CROSS APPLY вычисляет пару столбцов rsb (для крайнего правого установленного разряда) и prvrsb (для предшествующего правого установленного разряда). Как уже отмечалось, крайний правый установленный разряд представляет самый высокий активный приоритет (самое малое число). При использовании дополнения двоичного числа для целого числа N крайний правый установленный разряд вычисляется по формуле N & -N, где & — поразрядный оператор AND в T-SQL. Столбец rsb часто вычисляется как ptybitmap & -ptybitmap. Чтобы выяснить, каким было двоичное представление целого до применения текущего события, достаточно вычесть ptybitval из ptybitmap. Поэтому prvrsb вычисляется следующим образом:
(ptybitmap — ptybitval) & — (ptybitmap — ptybitval).
Второй оператор APPLY вычисляет два дополнительных столбца результатов с именами startpty и endpty. Они основаны на rsb и prvrsb, и потому для их расчета требуется отдельный оператор CROSS APPLY.
Столбец startpty
Если текущее событие начала или завершения начинает новый результирующий интервал, столбец startpty возвращает приоритет этого интервала, в противном случае — NULL. Одно условие, которое делает текущее событие началом результирующего интервала: событие является событием начала (type = 1), а самый высокий активный приоритет — приоритет текущего события (rsb = ptybitval). В таком случае startpty устанавливается равным pty (приоритет текущего события). Посмотрите на рисунок 1 и таблицу 3: можете ли вы определить случаи, относящиеся к этой категории? Один пример — событие начала интервала для User2 в 8:00 с приоритетом 3. Обратите внимание, что это событие начала является одновременно началом упакованного интервала и началом выходного интервала.
Другое условие, которое делает текущее событие началом результирующего интервала: событие представляет собой событие завершения (type = —1), а самый высокий оставшийся активный приоритет ниже приоритета только что завершившегося интервала (номер больше: rsb > -ptybitval). В этом случае для startpty установлен приоритет, который представлен rsb (вычисляется как LOG (rsb, 2) + 1). Например, в 9:30 завершается упакованный интервал для User2 с приоритетом 1. Это указывает на начало выходного интервала с приоритетом 2.
1. Постановка задачи;
2. Шаг 1 ;
3.
4. Шаг 4 и оптимизация решения с использованием APPLY.
Программный код, реализующий шаг 2, показан ниже, а выходные данные этого шага приведены в таблице, представленной также чуть ниже.
В программном коде определено обобщенное табличное выражение C3 на основе внешнего запроса из шага 1. Внешний запрос на шаге 2 направлен к СЗ и использует два оператора CROSS APPLY для вычисления нескольких столбцов результатов. Первый оператор CROSS APPLY вычисляет пару столбцов rsb (для крайнего правого установленного разряда) и prvrsb (для предшествующего правого установленного разряда). Как уже отмечалось, крайний правый установленный разряд представляет самый высокий активный приоритет (самое малое число). При использовании дополнения двоичного числа для целого числа N крайний правый установленный разряд вычисляется по формуле N & -N, где & — поразрядный оператор AND в T-SQL. Столбец rsb часто вычисляется как ptybitmap & -ptybitmap. Чтобы выяснить, каким было двоичное представление целого до применения текущего события, достаточно вычесть ptybitval из ptybitmap. Поэтому prvrsb вычисляется следующим образом:
(ptybitmap — ptybitval) & — (ptybitmap — ptybitval).
Второй оператор APPLY вычисляет два дополнительных столбца результатов с именами startpty и endpty. Они основаны на rsb и prvrsb, и потому для их расчета требуется отдельный оператор CROSS APPLY.
Столбец startpty
Если текущее событие начала или завершения начинает новый результирующий интервал, столбец startpty возвращает приоритет этого интервала, в противном случае — NULL. Одно условие, которое делает текущее событие началом результирующего интервала: событие является событием начала (type = 1), а самый высокий активный приоритет — приоритет текущего события (rsb = ptybitval). В таком случае startpty устанавливается равным pty (приоритет текущего события). Посмотрите на рисунок 1 и таблицу 3: можете ли вы определить случаи, относящиеся к этой категории? Один пример — событие начала интервала для User2 в 8:00 с приоритетом 3. Обратите внимание, что это событие начала является одновременно началом упакованного интервала и началом выходного интервала.
Другое условие, которое делает текущее событие началом результирующего интервала: событие представляет собой событие завершения (type = —1), а самый высокий оставшийся активный приоритет ниже приоритета только что завершившегося интервала (номер больше: rsb > -ptybitval). В этом случае для startpty установлен приоритет, который представлен rsb (вычисляется как LOG (rsb, 2) + 1). Например, в 9:30 завершается упакованный интервал для User2 с приоритетом 1. Это указывает на начало выходного интервала с приоритетом 2.