Tengo dos números como entrada del usuario, como por ejemplo 1000
y 1050
.
¿Cómo genero los números entre estos dos números, usando una consulta sql, en filas separadas? Quiero esto:
1000
1001
1002
1003
.
.
1050
sql
sql-server
tsql
sql-server-2008
usuario3211705
fuente
fuente
Una solución alternativa es el CTE recursivo:
fuente
Demo
Tenga en cuenta que esta tabla tiene un máximo de 2048 porque los números tienen espacios en blanco.
Aquí hay un enfoque ligeramente mejor usando una vista del sistema (desde SQL-Server 2005):
Demo
o use una tabla de números personalizada. Créditos a Aaron Bertrand, sugiero leer el artículo completo: generar un conjunto o secuencia sin bucles
fuente
WHERE type = 'P'
y evitarSELECT DISTINCT
String index out of range: 33
Recientemente escribí esta función con valores de tabla en línea para resolver este mismo problema. No está limitado en su alcance además de la memoria y el almacenamiento. No tiene acceso a tablas, por lo que no hay necesidad de lecturas o escrituras de disco en general. Agrega valores de combinaciones exponencialmente en cada iteración, por lo que es muy rápido incluso para rangos muy grandes. Crea diez millones de registros en cinco segundos en mi servidor. También funciona con valores negativos.
También es útil para rangos de fecha y hora:
Puede usar una combinación cruzada para dividir registros en función de los valores de la tabla. Entonces, por ejemplo, para crear un registro por cada minuto en un rango de tiempo en una tabla, podría hacer algo como:
fuente
SELECT X FROM fn_ConsecutiveNumbers(5, 500) ORDER BY X;
La mejor opción que he usado es la siguiente:
He generado millones de registros usando esto y funciona perfecto.
fuente
¡Funciona para mí!
fuente
sys.all_objects
, para rangos pequeños <2000 elementos, esto no es un problema. ¿No está seguro si tendrá problemas de permisos? perfecto para generar rápidamente un lote de datos de prueba.select top 50 ROW_NUMBER() over(order by a.name) + 1000 as Rcount from sys.all_objects a, sys.all_objects b
. Donde antes solo podía generar 2384 filas, ahora puedo generar 5683456 filas.La mejor manera es usar ctes recursivos.
saludos
fuente
fuente
Si no tiene problemas para instalar un ensamblado CLR en su servidor, una buena opción es escribir una función con valores de tabla en .NET. De esa manera, puede usar una sintaxis simple, lo que facilita unirse con otras consultas y, como bonificación, no desperdiciará memoria porque el resultado se transmite.
Cree un proyecto que contenga la siguiente clase:
Coloque el ensamblaje en algún lugar del servidor y ejecute:
Ahora puedes ejecutar:
fuente
Nada nuevo, pero reescribí la solución Brian Pressler para que sea más fácil de ver, podría ser útil para alguien (incluso si es solo para mí):
fuente
ROW_NUMBER()
no tienen ese problema.2 años después, pero descubrí que tenía el mismo problema. Así es como lo resolví. (editado para incluir parámetros)
fuente
La respuesta de slartidan se puede mejorar, en cuanto al rendimiento, eliminando todas las referencias al producto cartesiano y utilizando en su
ROW_NUMBER()
lugar ( plan de ejecución comparado ):Envuélvalo dentro de un CTE y agregue una cláusula where para seleccionar los números deseados:
fuente
SELECT ROW_NUMBER() OVER (...) - 1 AS n
. En algunos casos, esto podría matar el rendimiento.Aquí hay un par de soluciones óptimas y compatibles:
fuente
select
ingwhere spt_values.number between @min and @max
?Sé que llego 4 años tarde, pero me encontré con otra respuesta alternativa a este problema. El problema de la velocidad no es solo el prefiltrado, sino también la prevención de la clasificación. Es posible forzar la ejecución del orden de unión de una manera que el producto cartesiano realmente cuente como resultado de la unión. Usando la respuesta de slartidan como punto de partida:
Si conocemos el rango que queremos, podemos especificarlo a través de @Upper y @Lower. Al combinar la sugerencia de combinación REMOTE junto con TOP, podemos calcular solo el subconjunto de valores que queremos sin desperdiciar nada.
La sugerencia de unión REMOTO obliga primero al optimizador a comparar en el lado derecho de la unión. Al especificar cada combinación como REMOTO desde el valor más significativo hasta el menos significativo, la combinación en sí contará correctamente hacia arriba. No es necesario filtrar con un DÓNDE ni ordenar con un ORDER BY.
Si desea aumentar el rango, puede continuar agregando combinaciones adicionales con órdenes de magnitud progresivamente más altos, siempre que estén ordenadas de mayor a menor en la cláusula FROM.
Tenga en cuenta que esta es una consulta específica para SQL Server 2008 o superior.
fuente
Esto también servirá
fuente
La mejor velocidad cuando se ejecuta la consulta
fuente
CTE recursivo en tamaño exponencial (incluso para el valor predeterminado de 100 recursiones, esto puede generar hasta 2 ^ 100 números):
fuente
@startnum
yendnum
debería ser ingresado por el usuario?Tuve que insertar una ruta de archivo de imagen en la base de datos utilizando un método similar. La consulta a continuación funcionó bien:
El código para ti sería:
fuente
Esto es lo que hago, es bastante rápido y flexible y no tiene mucho código.
Tenga en cuenta que (ORDER BY @count) es un maniquí. No hace nada, pero ROW_NUMBER () requiere un ORDER BY.
Editar : me di cuenta de que la pregunta original era obtener un rango de x a y. Mi script se puede modificar así para obtener un rango:
fuente
fuente
Esto solo funciona para secuencias siempre que alguna tabla de aplicaciones tenga filas. Suponga que quiero la secuencia de 1..100, y tengo la tabla de aplicaciones dbo.foo con columna (de tipo numérico o de cadena) foo.bar:
A pesar de su presencia en un orden por cláusula, dbo.foo.bar no tiene que tener valores distintos o incluso no nulos.
Por supuesto, SQL Server 2012 tiene objetos de secuencia, por lo que hay una solución natural en ese producto.
fuente
Esto es lo que se me ocurrió:
Genera hasta 2 ^ 24 valores. Las condiciones de unión lo mantienen rápido para valores pequeños.
fuente
Esto se completó para mí en 36 segundos en nuestro servidor DEV. Al igual que la respuesta de Brian, centrarse en filtrar al rango es importante desde la consulta; un ENTRE todavía intenta generar todos los registros iniciales antes del límite inferior a pesar de que no los necesita.
Tenga en cuenta que ROW_NUMBER es un bigint , por lo que no podemos repasar 2 ^^ 64 (== 16 ^^ 16) registros generados con ningún método que lo use. Por lo tanto, esta consulta respeta el mismo límite superior para los valores generados.
fuente
Esto usa código de procedimiento y una función con valores de tabla. Lento, pero fácil y predecible.
Uso:
Es una tabla, por lo que puede usarla junto con otros datos. Con mayor frecuencia uso esta función como el lado izquierdo de una unión contra un GROUP BY hora, día, etc. para garantizar una secuencia contigua de valores de tiempo.
El rendimiento es poco inspirador (16 segundos para un millón de filas) pero lo suficientemente bueno para muchos propósitos.
fuente
Oráculo 12c; Rápido pero limitado:
Nota : limitado al recuento de filas de la vista all_objects;
fuente
La solución que he desarrollado y utilizado desde hace bastante tiempo (montar algunos en los trabajos compartidos de otros) es ligeramente similar a al menos uno publicado. No hace referencia a ninguna tabla y devuelve un rango sin clasificar de hasta 1048576 valores (2 ^ 20) y puede incluir negativos si lo desea. Por supuesto, puede ordenar el resultado si es necesario. Funciona bastante rápido, especialmente en rangos más pequeños.
fuente
fuente
Hice la siguiente función después de leer este hilo. Simple y rápido
fuente