Eu tenho dois números como entrada do usuário, como por exemplo 1000
e 1050
.
Como faço para gerar os números entre esses dois números, usando uma consulta sql, em linhas separadas? Eu quero isso:
1000
1001
1002
1003
.
.
1050
sql
sql-server
tsql
sql-server-2008
user3211705
fonte
fonte
uma solução alternativa é CTE recursiva:
fonte
Demo
Observe que esta tabela tem no máximo 2048 porque os números têm lacunas.
Aqui está uma abordagem um pouco melhor usando uma exibição do sistema (desde o SQL-Server 2005):
Demo
ou use uma tabela numérica personalizada. Créditos a Aaron Bertrand, sugiro ler o artigo inteiro: Gere um conjunto ou sequência sem loops
fonte
WHERE type = 'P'
e evitarSELECT DISTINCT
String index out of range: 33
Recentemente, escrevi esta função com valor de tabela embutida para resolver esse mesmo problema. Seu alcance não é limitado, exceto memória e armazenamento. Ele não acessa tabelas, portanto não há necessidade de leituras ou gravações de disco em geral. Ele adiciona valores de associações exponencialmente em cada iteração, tornando-o muito rápido, mesmo para intervalos muito grandes. Ele cria dez milhões de registros em cinco segundos no meu servidor. Também funciona com valores negativos.
É útil também para períodos e datas:
Você pode usar uma junção de aplicação cruzada nela para dividir registros com base nos valores na tabela. Por exemplo, para criar um registro para cada minuto em um intervalo de tempo em uma tabela, você pode fazer algo como:
fonte
SELECT X FROM fn_ConsecutiveNumbers(5, 500) ORDER BY X;
A melhor opção que usei é a seguinte:
Eu gerei milhões de registros usando isso e funciona perfeitamente.
fonte
Isso funciona para mim!
fonte
sys.all_objects
- para pequenos intervalos <2000 itens, isso não é um problema. Não tem certeza se ele terá problemas de permissões? perfeito para gerar rapidamente um lote de dados de teste.select top 50 ROW_NUMBER() over(order by a.name) + 1000 as Rcount from sys.all_objects a, sys.all_objects b
. Onde eu só podia gerar 2384 linhas antes, agora posso gerar 5683456 linhas.A melhor maneira é usar ctes recursivas.
saludos.
fonte
fonte
Se você não tiver problemas para instalar um assembly CLR no servidor, uma boa opção é escrever uma função com valor de tabela no .NET. Dessa forma, você pode usar uma sintaxe simples, facilitando a associação com outras consultas e, como bônus, não desperdiçará memória porque o resultado é transmitido.
Crie um projeto contendo a seguinte classe:
Coloque o assembly em algum lugar no servidor e execute:
Agora você pode executar:
fonte
Nada de novo, mas eu reescrevi a solução Brian Pressler para ficar mais fácil, pode ser útil para alguém (mesmo que seja apenas para mim):
fonte
ROW_NUMBER()
não têm esse problema.Dois anos depois, mas descobri que tinha o mesmo problema. Aqui está como eu resolvi isso. (editado para incluir parâmetros)
fonte
a resposta de slartidan pode ser melhorada, em termos de desempenho, eliminando todas as referências ao produto cartesiano e usando-o
ROW_NUMBER()
(em comparação com o plano de execução ):Coloque-o dentro de um CTE e adicione uma cláusula where para selecionar os números desejados:
fonte
SELECT ROW_NUMBER() OVER (...) - 1 AS n
. Em alguns casos, isso pode prejudicar o desempenho.Aqui estão algumas soluções ótimas e compatíveis:
fonte
select
ingwhere spt_values.number between @min and @max
?Sei que estou quatro anos atrasado, mas me deparei com outra resposta alternativa para esse problema. O problema da velocidade não é apenas a pré-filtragem, mas também a prevenção da classificação. É possível forçar a ordem de junção para executar da maneira que o produto cartesiano realmente conta como resultado da junção. Usando a resposta de slartidan como ponto de partida:
Se soubermos o intervalo que queremos, podemos especificá-lo via @Upper e @Lower. Ao combinar a dica de junção REMOTE e TOP, podemos calcular apenas o subconjunto de valores que queremos sem desperdiçar nada.
A dica de junção REMOTE força o otimizador a comparar primeiro o lado direito da junção. Ao especificar cada junção como REMOTE do valor mais ao menos significativo, a junção em si contará mais uma vez corretamente. Não há necessidade de filtrar com um WHERE ou classificar com um ORDER BY.
Se você deseja aumentar o intervalo, pode continuar a adicionar junções adicionais com ordens de magnitude progressivamente mais altas, desde que ordenadas da mais para a menos significativa na cláusula FROM.
Observe que esta é uma consulta específica para o SQL Server 2008 ou superior.
fonte
Isso também fará
fonte
A melhor velocidade ao executar a consulta
fonte
CTE recursivo em tamanho exponencial (mesmo com o padrão de 100 recursões, isso pode gerar até 2 ^ 100 números):
fonte
@startnum
eendnum
deve ser inserido pelo usuário?Eu tive que inserir o caminho do arquivo de imagem no banco de dados usando um método semelhante. A consulta abaixo funcionou bem:
O código para você seria:
fonte
É isso que eu faço, é bem rápido e flexível e não tem muito código.
Observe que (ORDER BY @count) é um manequim. Não faz nada, mas ROW_NUMBER () requer um ORDER BY.
Edit : eu percebi que a pergunta original era obter um intervalo de x até y. Meu script pode ser modificado assim para obter um intervalo:
fonte
fonte
Isso funciona apenas para seqüências, desde que algumas tabelas de aplicativos tenham linhas. Suponha que eu queira a sequência de 1..100 e tenha a tabela de aplicativos dbo.foo com a coluna (do tipo numérico ou de seqüência de caracteres) foo.bar:
Apesar de estar presente em uma cláusula order by, o dbo.foo.bar não precisa ter valores distintos ou mesmo nulos.
Obviamente, o SQL Server 2012 tem objetos de sequência, então há uma solução natural nesse produto.
fonte
Aqui está o que eu vim com:
Gera até 2 ^ 24 valores. As condições de junção mantêm-no rápido para valores pequenos.
fonte
Isso foi concluído em 36 segundos em nosso servidor DEV. Como a resposta de Brian, o foco na filtragem para o intervalo é importante na consulta; a BETWEEN ainda tenta gerar todos os registros iniciais antes do limite inferior, mesmo que não precise deles.
Note-se que ROW_NUMBER é um bigint , por isso não podemos passar por cima de 2 ^^ 64 (== 16 ^^ 16) registros gerados com qualquer método que usa-lo. Esta consulta, portanto, respeita o mesmo limite superior nos valores gerados.
fonte
Isso usa código processual e uma função com valor de tabela. Lento, mas fácil e previsível.
Uso:
É uma tabela, para que você possa usá-lo em junções com outros dados. Eu frequentemente uso essa função como o lado esquerdo de uma junção contra um GROUP BY hora, dia etc. para garantir uma sequência contígua de valores de tempo.
O desempenho não é inspirador (16 segundos para um milhão de linhas), mas é bom o suficiente para muitos propósitos.
fonte
Oracle 12c; Rápido, mas limitado:
Nota : limitado à contagem de linhas da visualização all_objects;
fonte
A solução que eu desenvolvi e usei há algum tempo (usando alguns dos trabalhos compartilhados de outros) é um pouco semelhante a pelo menos um postado. Ele não faz referência a nenhuma tabela e retorna um intervalo não classificado de até 1048576 valores (2 ^ 20) e pode incluir negativos, se desejado. Obviamente, você pode classificar o resultado, se necessário. Ele roda muito rapidamente, especialmente em faixas menores.
fonte
fonte
Eu fiz a função abaixo depois de ler este tópico. Simples e rápido:
fonte