2011-06-30 14 views
13

¿Hay una manera de seleccionar un número específico de filas sin crear una tabla. p.ej. Si utilizo el siguiente:Select de SQL 'n' registros sin una tabla

SELECT 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 

Se me dará el 10 de ancho, quiero 10 filas nuevas.

Gracias

+1

PostgreSQL tiene una función GENERATE_SERIES() que hace precisamente esto. No sé qué otros DB podrían hacer algo similar. Probablemente pueda escribir un procedimiento almacenado para hacerlo si dicha función no existe en SQL Server. – Flimzy

Respuesta

26

Se puede utilizar un recursive CTE para generar una secuencia arbitraria de números en T-SQL como tal :

DECLARE @start INT = 1; 
DECLARE @end INT = 10; 

WITH numbers AS (
    SELECT @start AS number 
    UNION ALL 
    SELECT number + 1 
    FROM numbers 
    WHERE number < @end 
) 
SELECT * 
FROM numbers 
OPTION (MAXRECURSION 0); 
+0

+1 - ¡Maldita sea que me hayas vencido! –

+0

¡Perfecto! Gracias – James

+0

Realista sin embargo, si quiero un millón de números, está bien recurse 1 millón de veces? – Triynko

16

Si usted tiene un número fijo de filas, que puede probar:

SELECT 1 
UNION 
SELECT 2 
UNION 
SELECT 3 
UNION 
SELECT 4 
UNION 
SELECT 5 
UNION 
SELECT 6 
UNION 
SELECT 7 
UNION 
SELECT 8 
UNION 
SELECT 9 
UNION 
SELECT 10 
+0

Esto también es genial, ¡gracias! – James

4
SELECT 1 
UNION 
SELECT 2 
UNION 
... 
UNION 
SELECT 10 ; 
7

Esta es una buena manera si necesita una lista larga (por lo que no necesita una gran cantidad de UNION Indicaciones:

WITH CTE_Numbers AS (
    SELECT n = 1 
    UNION ALL 
    SELECT n + 1 FROM CTE_Numbers WHERE n < 10 
) 
SELECT n FROM CTE_Numbers 
+0

Es bueno, pero tiene el límite máximo de recusrión. –

+1

Si quiere rebasar el límite predeterminado, puede usar la opción como lo hizo Dave. El límite en eso es 32767. Todavía es un límite, pero mejor que 32767 'UNION' TODAS las declaraciones! ;-) –

+0

¡Sí, es cierto! Intenté con Dave's en SQL-Server Express 2005 y se ejecutó en 100000 sin ningún problema. –

2

Uso de pivote (para algunos casos, sería una exageración)

DECLARE @Items TABLE(a int, b int, c int, d int, e int); 

INSERT INTO @Items 
VALUES(1, 2, 3, 4, 5) 

SELECT Items 
FROM @Items as p 
UNPIVOT  
(Items FOR Seq IN   
([a], [b], [c], [d], [e])) AS unpvt 
+0

muy creativa, me encanta 1 –

+0

@ t-clausen.dk, Gracias hombre :) – sll

-1
;WITH nums AS 
    (SELECT 1 AS value 
    UNION ALL 
    SELECT value + 1 AS value 
    FROM nums 
    WHERE nums.value <= 99) 
SELECT * 
FROM nums 
+0

Algunos comentario o descripción no sería tan malo ;-) – t3chb0t

+0

ya hay dos respuestas que muestran el CTE recursiva. ¿Qué agrega tu respuesta que aún no se haya dicho? –

7

El enfoque recursivo CTE - es realmente bueno.

ser sólo consciente de diferencia de rendimiento. Vamos a jugar con un millón de registros:

enfoque CTE recursiva. Duración = 14 segundos

declare @start int = 1; 
declare @end int = 999999; 

with numbers as 
(
    select @start as number 
    union all 
    select number + 1 from numbers where number < @end 
) 
select * from numbers option(maxrecursion 0); 

Unión Todo + Cruz de Ingreso enfoque. Duración = 6 segundos

with N(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 
) 
select top 999999 
    row_number() over(order by (select 1)) as number 
from 
    N n1, N n2, N n3, N n4, N n5, N n6; 

Tabla Valor Constructor + Cruz de Ingreso enfoque. Duración = 6 segundos

(si SQL Server> = 2008)

with N as 
(
    select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t(n)  
) 
select top 999999 
    row_number() over(order by (select 1)) as number 
from 
    N n1, N n2, N n3, N n4, N n5, N n6; 

CTE recursiva + Cruz de Ingreso enfoque. :) Duración = 6 segundos

with N(n) as 
(
    select 1 
    union all 
    select n + 1 from N where n < 10  
) 
select top 999999 
    row_number() over(order by (select 1)) as number 
from 
    N n1, N n2, N n3, N n4, N n5, N n6; 

Obtendremos efecto más sorprendente si se intenta insertar el resultado en una variable de tabla:

INSERT INTO con enfoque recursivo CTE.Duración = 17 segundos

declare @R table (Id int primary key clustered); 

with numbers as 
(
    select 1 as number 
    union all 
    select number + 1 from numbers where number < 999999 
) 
insert into @R 
select * from numbers option(maxrecursion 0); 

INSERT INTO con enfoque de Ingreso Cruz. Duración = 1 segundo

declare @C table (Id int primary key clustered); 

with N as 
(
    select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t(n)  
) 
insert into @C 
select top 999999 
    row_number() over(order by (select 1)) as number 
from 
    N n1, N n2, N n3, N n4, N n5, N n6; 

Aquí es un interesante artículo sobre Tally Tables

1

Usando la tabla spt_values:

SELECT TOP (1000) n = ROW_NUMBER() OVER (ORDER BY number) 
FROM [master]..spt_values ORDER BY n; 

O si el valor que se necesita es menos de 1k:

SELECT DISTINCT n = number FROM master..[spt_values] WHERE number BETWEEN 1 AND 1000; 

Esta es una tabla que se utiliza por los procedimientos almacenados internos para diversos fines. Su uso en línea parece ser bastante frecuente, incluso si no está documentado, no es compatible, puede desaparecer un día y porque solo contiene un conjunto de valores finitos, no únicos y no contiguos. Hay 2,164 valores únicos y 2,508 totales en SQL Server 2008 R2; en 2012 hay 2.167 únicos y 2.515 en total. Esto incluye duplicados, valores negativos, e incluso si se usa DISTINCT, muchos vacíos una vez que se supera el número 2,048. Por lo tanto, la solución consiste en utilizar ROW_NUMBER() para generar una secuencia contigua, comenzando en 1, según los valores de la tabla.

Además, para ayudar a más valores que 2k registros, puede unirse a la tabla consigo mismo, pero en casos comunes, esa tabla en sí misma es suficiente.

En cuanto al rendimiento, no debería ser demasiado malo (que genera un millón de discos, se tardó 10 segundos en mi portátil), y la consulta es bastante fácil de leer.

Fuente: http://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1

Cuestiones relacionadas