2010-07-13 3 views
5

Есть ли SQL-запрос, я могу сделать это будет генерировать линейную последовательность какСуществует ли общий способ генерации произвольной линейной последовательности в SQL?

1, 2, 3, 4, 5, 6, 7 ... x+1 

или

2, 7, 12, 17, 22 ... 2+5x 

(где каждое число является записью в строке полученной таблицы)

+0

Есть ли какая-то причина для этого в SQL, а не на уровне приложения? – Borealid

+1

@Borealid - часто полезно иметь таблицу дополнительных номеров в SQL. –

+0

@Borealid: Если бы я мог создать такую ​​таблицу, то, я полагаю, я мог бы использовать ее для создания более сложных запросов; Если я сгенерировал его в приложении, я думаю, что застрял бы с супер длинными операторами SQL с последовательностью, встроенной в них. –

ответ

1

№ (Если предварительная обработка таблицы чисел считается общим способом.)

В SQL Server это можно сделать с помощью рекурсивного CTE или генератора ИНГ последовательность, используя ROW_NUMBER()

0

Использование последовательности

3

SQL Server и Oracle в настоящее время реализовать стандартный ROW_NUMBER ANSI() функции кадрирования, но вам нужен стол, чтобы отрабатывать:

SELECT ROW_NUMBER() OVER (ORDER BY ID) AS __ROW, ID, Name 
FROM SomethingWithANameAndAnID 
ORDER BY __ROW; 

Или вы могли бы использовать рекурсивную Common Table Expression в SQL Server (не уверен, если Oracle реализует это еще):

WITH cte AS 
(
    SELECT 1 AS num 
    UNION ALL 
    SELECT (num + 1) AS num FROM cte 
    WHERE num < @SomeMaximum 
) 
SELECT * FROM cte OPTION (MAXRECURSION 0); 

Обратите внимание, что без опции MAXRECURSION КТР глубина рекурсии в MS SQL ограничено до 100. (значение 0 отключает предел рекурсии)

0

В Oracle вы можете сделать:

select ROWNUM linear_sequence from dual CONNECT BY LEVEL <= x; 

где х это конец последовательность.

+0

Или (для варианта варианта OP): выберите (ROWNUM-1) * 5 + 2 AS linear_sequence из двойного CONNECT BY LEVEL <= x; –

0

Вы можете задать приращение при создании последовательности:

CREATE SEQUENCE mysequence INCREMENT BY 5 START WITH 2; 
2

Если производительность вашей заботы, есть эта UDF готова:

create function [dbo].[Numbers](@count bigint) 
RETURNS TABLE RETURN 
with byte (n) as (select 1 from (VALUES 
     (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1) 
     ) x(n) ) 
, byte2 (n) as (select 1 from byte a, byte b) 
, byte4 (n) as (select 1 from byte2 a, byte2 b) 
, byte8 (n) as (select 1 from byte4 a, byte4 b) 
select top(@count) n = ROW_NUMBER() over(order by n) from byte8 

По-видимому, рекурсия только КТР сгенерированной порядковый номер работы, но очень медленно. Здесь мы продаем некоторый объем кода для огромного увеличения производительности. Это дает мне более 30 миллионов номеров за 8 секунд на моем дерьмовом перегруженном ПК. Он может зайти так далеко, как вы хотите, и может позволить себе предел максимума bigint.

Он не будет касаться диска IO, если оптимизатор не выберет его из памяти (вряд ли когда-либо для разумного сценария). Это также позволит избежать ожиданий и тупиков, в отличие от решений на основе физических таблиц.

Использование так:

select 2 + n*5 from Numbers(100) 

Вы должны быть в состоянии создать представление, как это.

Для тех, кому не требуется фактическое число, просто строки, удаляющие материал row_number, ускоряют его дважды.

Вдохновленный http://weblogs.sqlteam.com/jamesn/archive/2008/05/29/60612.aspx (Ицик Бен Ган, упомянутый С. Нейманом). Эта версия поставляется с более простым планом выполнения и делает возможности возможными, вот о преимуществах.

+0

Сравнивает производительность с аналогичным решением здесь http://stackoverflow.com/a/16605089/481812 – Rbjz

+0

Доказательство того, что теперь можно взять bigint 'select count_big (1) из [dbo]. [Numbers] (2147483650)' взял 2 минут – Rbjz

Смежные вопросы