Для многих задач полезно иметь под рукой дополнительные таблицы. Одной из таких таблиц является таблица с последовательным набором чисел Numbers. Ее можно использовать как для создания тестовых таблиц с данными, так и для прикладных задач. Особенно полезны для работы со строками, для их итеративной обработки.
Существует множество способов создания такой таблицы:
Существует множество способов создания такой таблицы:
- master..spt_values
- row_number() с любой таблицей, например sys.all_objects
- CTE
- Рекурсивный CTE
- Цикл
spt_values
Можно ничего не генерировать, а воспользоваться данной стандартной таблицей. Она содержит 2048 последовательных значения:
select number from master.dbo.spt_values where type = 'P'
row_number()
Если необходимо больше значений, можно сделать cross join таблицы master..spt_values и воспользоваться функцией row_number(), ограничивая набор нужным количеством строкselect top(1000000) row_number() over(order by s1.number) as number from master..spt_values s1, master..spt_values s2 option (maxdop 1)
CTE
Следующий вариант генерации последовательного набора чисел -- воспользоваться механизмом табличных выражений CTE. Данная реализация менее компактна, нежели предыдущая.
;with t10(n) as ( select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 ), t1000(n) as ( select 1 from t10 a, t10 b, t10 c ), t1000000(n) as ( select 1 from t1000 a, t1000 b ) select row_number() over(order by n) as number from t1000000;
Recursive CTE
Вариант с рекурсивным табличным выражением более компактный, но работает значительно дольше, чем свои конкуренты. Вообще, я стараюсь избегать рекурсивных запросов, особенно на больших таблицах
;with Numbers(num) as ( select 1 as num union all select num + 1 as num from Numbers where num < 1000000 ) select num from Numbers option (maxrecursion 0)
Хоть и по приведенным ниже ссылкам уже производится сравнения, приведу собственные замеры по времени выполнения данных методов. При тестировании результаты запросов записывались во временную таблицу
Таблица Numbers
Для себя я использую следующий скрипт и храню таблицу Numbers под рукой.
if object_id('dbo.Numbers', 'U') is not null drop table dbo.Numbers select top(1000000) n = row_number() over(order by s1.number) into dbo.Numbers from master..spt_values s1, master..spt_values s2 option (maxdop 1); create unique clustered index ix_numbers_n on dbo.Numbers(n)