Это можно сделать с помощью функции NTILE()
, но я не думаю, что она более эффективна, чем ROW_NUMBER()
, главным образом потому, что этот метод должен получить общее количество, чтобы определить количество групп.
Создание тестовой среды:
/* -- SQL 2016
DROP TABLE IF EXISTS #test;
GO
*/
IF OBJECT_ID('tempdb.dbo.#test') IS NOT NULL DROP TABLE #test
CREATE TABLE #test(period INT);
GO
INSERT INTO #test -- Make it bigger
VALUES (602),(603),(604),(605),(606),(607),(608),(609);
GO 51
ROW_NUMBER Метод:
SELECT /*ROW_NUM*/ period,
(Row_number()OVER(ORDER BY period) - 1)/3 + 1
FROM #test;
GO
IO и время выступления: укороченные для удобства чтения
(400 строк (а)) Таблица «Рабочий стол». Число сканирования 0, логическое чтение 0, физическое значение 0 '# test_00000000000E'. Количество сканирования 1, логического чтения 1, физических чтений 0
(1 строку (ы) пострадавших)
SQL-сервера Выполнение Время: процессорного времени = 0 мс, затраченное время = 85 мс .
NTILE Метод
DECLARE @ntile_var int;
SELECT @ntile_var = COUNT(*) FROM #test;
SELECT /*NTILE*/period
, NTILE(@ntile_var/3) OVER (ORDER BY period)
FROM #test
IO и времени выступления: Укороченные для удобочитаемости
SQL Server синтаксического анализа и время компиляции: процессорного времени = 0 мс, затраченное время = 0 мс.
Время выполнения SQL Server: время процессора = 0 мс, прошедшее время = 0 мс.
SQL Server анализирует и компилирует время: CPU time = 0 мс, прошедшее время = 0 мс.
Таблица '# test__00000000000E'. Количество сканирования 1, логического чтения 1, физических чтений 0
(1 строку (ы) пострадавших)
SQL-сервера Выполнение Время: процессорного времени = 0 мс, прошедшее время = 0 мс.
(400 строк (а)) Таблица «Рабочий стол». Число сканирования 3, логические значения 811, физические данные 0 Таблица '#test ___ 00000000000E'. Количество сканирования 1, логического чтения 1, физических чтений 0
(1 строку (ы) пострадавших)
SQL Выполнение сервера Время: процессорного времени = 0 мс, затраченное время = 93
Оба они дают те же результаты:
Но есть предостережение! MSDN положить его в достаточной степени, как (подчеркивание добавлено)
Если число строк в разделе не делится на integer_expression, это вызовет группу из двух размеров, отличающихся один членом. Большие группы относятся к меньшим группам в порядке , указанном в предложении OVER. Например, если общее число строк равно 53, а число групп равно пяти, первые три группы будут имеют 11 строк, а две оставшиеся группы будут иметь по 10 строк.
Так с помощью метода NTILE, вы могли бы получить несколько групп 4, так что остальные из них могут быть 3.
Насколько мне известно, нет лучшего способа сделать это. В конце концов, это то, для чего был разработан ROW_NUMBER, нет? Почему вы хотите использовать другой подход? – Tyron78
Почему вы хотите использовать другой метод, если это работает нормально? Есть ли причина, по которой вы хотите сделать это более математически? – Saypontigohe
@Saypontigohe & @ Tyron78 - Исходный путь требования более сложный, чем этот.Я использую эту последовательность в 'partition by 'другой функции окна. Из-за запроса 'Row_Number' становится очень медленным –