2010-07-13 26 views
5

¿Existe una consulta SQL que pueda hacer que generará una secuencia lineal como¿Existe una forma genérica de generar una secuencia lineal arbitraria en SQL?

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

o

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

(donde cada número es una entrada en una fila de la tabla resultante)

+0

¿Hay alguna razón para hacer esto en SQL y no en el nivel de aplicación? – Borealid

+1

@Borealid - A menudo es útil tener una tabla de Números Auxiliares en SQL. –

+0

@Borealid: Si pudiera generar una tabla de este tipo, creo que podría usarla para crear consultas más complejas; Si lo genero en la aplicación, creo que me quedaré atrapado con sentencias SQL super largas con la secuencia integrada en ellas. –

Respuesta

1

No. (A menos que la preventa de una tabla de números cuente como una forma genérica.)

En SQL Server, esto se puede hacer con un CTE recursivo o generat ing una secuencia utilizando ROW_NUMBER()

0

Uso secuencia

3

SQL Server y Oracle ahora implementar el estándar ANSI ROW_NUMBER() función ventana, pero se necesitaría una mesa para trabajar fuera de:

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

O usted podría utilizar una expresión de tabla común recursiva en SQL Server (no estoy seguro si Oracle implementa esto todavía):

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); 

Tenga en cuenta que sin la opción MAXRECURSION CTE nivel de recursividad en MS SQL se limita a 100. (valor de 0 desactiva el límite de recursión)

0

En Oracle que puede hacer:

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

donde x es el fin de la secuencia.

+0

O (para la serie de variantes de OP): seleccione (ROWNUM-1) * 5 + 2 AS sequence_lineal de dual CONNECT BY LEVEL <= x; –

0

Se puede especificar un incremento en la creación de una secuencia:

CREATE SEQUENCE mysequence INCREMENT BY 5 START WITH 2; 
2

Si el rendimiento es su preocupación, puesto esta UDF listo:

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 

Al parecer, la recursividad de sólo CTE obras generadas por secuencia de números, pero muy lento Aquí intercambiamos algún volumen de código por un gran aumento en el rendimiento. Este me da más de 30 millones de números en 8 segundos en mi horrible PC sobrecargada. Puede ir tan lejos como desee y puede pagar hasta el límite de bigint máximo.

No tocará el disco IO a menos que el optimizador lo elimine de la memoria (casi nunca para un escenario razonable). También evitará esperas y bloqueos a diferencia de las soluciones basadas en tablas físicas.

uso como esto:

select 2 + n*5 from Numbers(100) 

Usted debe ser capaz de crear una vista como esta.

Para aquellos que no requieren un número real, solo filas, eliminar el número de fila cosas lo acelera dos veces.

Inspirado por http://weblogs.sqlteam.com/jamesn/archive/2008/05/29/60612.aspx (Itzik Ben Gan mencionado por S. Neumann). Esta versión viene con un plan de ejecución más simple y hace posibles los grandes, eso es sobre las ventajas.

+0

Comparado el rendimiento con una solución similar aquí http://stackoverflow.com/a/16605089/481812 – Rbjz

+0

Una prueba de que ahora puede tomar bigint 'select count_big (1) from [dbo]. [Numbers] (2147483650)' tomó 2 minutos – Rbjz

Cuestiones relacionadas