J'ai deux nombres comme entrée de l'utilisateur, comme par exemple 1000
et 1050
.
Comment générer les nombres entre ces deux nombres, à l'aide d'une requête SQL, en lignes séparées? Je veux ceci:
1000
1001
1002
1003
.
.
1050
sql
sql-server
tsql
sql-server-2008
user3211705
la source
la source
une solution alternative est le CTE récursif:
la source
Demo
Notez que ce tableau a un maximum de 2048 car alors les nombres ont des lacunes.
Voici une approche légèrement meilleure utilisant une vue système (depuis SQL-Server 2005):
Demo
ou utilisez une table numérique personnalisée. Crédits à Aaron Bertrand, je propose de lire l'article en entier: Générer un ensemble ou une séquence sans boucles
la source
WHERE type = 'P'
et éviterSELECT DISTINCT
String index out of range: 33
J'ai récemment écrit cette fonction de table en ligne pour résoudre ce problème. Il n'est pas limité dans la plage autre que la mémoire et le stockage. Il n'accède à aucune table, il n'est donc pas nécessaire de lire ou d'écrire sur le disque en général. Il ajoute des valeurs de jointure de manière exponentielle à chaque itération, ce qui le rend très rapide même pour de très grandes plages. Il crée dix millions d'enregistrements en cinq secondes sur mon serveur. Cela fonctionne également avec des valeurs négatives.
C'est également pratique pour les plages de dates et d'heures:
Vous pouvez utiliser une jointure à application croisée pour diviser les enregistrements en fonction des valeurs de la table. Ainsi, par exemple, pour créer un enregistrement pour chaque minute sur une plage de temps dans une table, vous pouvez faire quelque chose comme:
la source
SELECT X FROM fn_ConsecutiveNumbers(5, 500) ORDER BY X;
La meilleure option que j'ai utilisée est la suivante:
J'ai généré des millions d'enregistrements en utilisant cela et cela fonctionne parfaitement.
la source
Ça marche pour moi!
la source
sys.all_objects
- pour les petites plages <2000 éléments, ce n'est pas un problème. Vous ne savez pas s'il aura des problèmes d'autorisations? parfait pour générer rapidement un lot de données de test.select top 50 ROW_NUMBER() over(order by a.name) + 1000 as Rcount from sys.all_objects a, sys.all_objects b
. Là où je ne pouvais générer que 2384 lignes auparavant, je peux maintenant générer 5683456 lignes.Le meilleur moyen est d'utiliser des ctes récursifs.
saludos.
la source
la source
Si vous ne rencontrez pas de problème pour installer un assembly CLR sur votre serveur, une bonne option consiste à écrire une fonction table dans .NET. De cette façon, vous pouvez utiliser une syntaxe simple, ce qui facilite la jonction avec d'autres requêtes et, en prime, ne gaspille pas de mémoire car le résultat est diffusé.
Créez un projet contenant la classe suivante:
Placez l'assemblage quelque part sur le serveur et exécutez:
Vous pouvez maintenant exécuter:
la source
Rien de nouveau mais j'ai réécrit la solution de Brian Pressler pour être plus agréable à l'œil, cela pourrait être utile à quelqu'un (même si c'est juste pour moi):
la source
ROW_NUMBER()
n'ont pas ce problème.2 ans plus tard, mais j'ai découvert que j'avais le même problème. Voici comment je l'ai résolu. (modifié pour inclure les paramètres)
la source
La réponse de slartidan peut être améliorée, en termes de performances, en éliminant toutes les références au produit cartésien et en utilisant à la
ROW_NUMBER()
place ( plan d'exécution comparé ):Enveloppez-le dans un CTE et ajoutez une clause where pour sélectionner les nombres souhaités:
la source
SELECT ROW_NUMBER() OVER (...) - 1 AS n
. Dans certains cas, cela peut nuire aux performances.Voici quelques solutions tout à fait optimales et compatibles:
la source
select
ingénieriewhere spt_values.number between @min and @max
?Je sais que j'ai 4 ans trop tard, mais je suis tombé sur une autre solution alternative à ce problème. Le problème de la vitesse n'est pas seulement le pré-filtrage, mais aussi la prévention du tri. Il est possible de forcer l'ordre de jointure à s'exécuter d'une manière que le produit cartésien compte réellement à la suite de la jointure. En utilisant la réponse de slartidan comme point de départ:
Si nous connaissons la plage que nous voulons, nous pouvons la spécifier via @Upper et @Lower. En combinant l'indicateur de jointure REMOTE avec TOP, nous pouvons calculer uniquement le sous-ensemble de valeurs que nous voulons sans rien perdre.
L'indication de jointure REMOTE force l'optimiseur à comparer en premier sur le côté droit de la jointure. En spécifiant chaque jointure comme REMOTE de la valeur la plus importante à la valeur la moins significative, la jointure elle-même comptera correctement de un. Pas besoin de filtrer avec un WHERE ou de trier avec un ORDER BY.
Si vous souhaitez augmenter la plage, vous pouvez continuer à ajouter des jointures supplémentaires avec des ordres de grandeur progressivement plus élevés, à condition qu'elles soient classées du plus important au moins significatif dans la clause FROM.
Notez qu'il s'agit d'une requête spécifique à SQL Server 2008 ou supérieur.
la source
Cela fera également
la source
La meilleure vitesse lors de l'exécution de la requête
la source
CTE récursif en taille exponentielle (même pour la récursivité par défaut de 100, cela peut générer jusqu'à 2 ^ 100 nombres):
la source
@startnum
etendnum
devrait être saisi par l'utilisateur?J'ai dû insérer le chemin du fichier image dans la base de données en utilisant une méthode similaire. La requête ci-dessous a bien fonctionné:
Le code pour vous serait:
la source
C'est ce que je fais, c'est assez rapide et flexible et peu de code.
Notez que (ORDER BY @count) est un mannequin. Il ne fait rien mais ROW_NUMBER () nécessite un ORDER BY.
Edit : J'ai réalisé que la question initiale était d'obtenir une plage de x à y. Mon script peut être modifié comme ceci pour obtenir une plage:
la source
la source
Cela ne fonctionne que pour les séquences tant que certaines tables d'application ont des lignes. Supposons que je veux une séquence de 1 à 100 et que la table d'application dbo.foo avec la colonne (de type numérique ou chaîne) foo.bar:
Malgré sa présence dans une clause order by, dbo.foo.bar n'a pas besoin d'avoir des valeurs distinctes ou même non nulles.
Bien sûr, SQL Server 2012 a des objets de séquence, il existe donc une solution naturelle dans ce produit.
la source
Voici ce que j'ai trouvé:
Génère jusqu'à 2 ^ 24 valeurs. Les conditions de jointure le maintiennent rapide pour les petites valeurs.
la source
Cela s'est terminé pour moi en 36 secondes sur notre serveur DEV. Comme la réponse de Brian, il est important de se concentrer sur le filtrage de la plage depuis la requête; a BETWEEN essaie toujours de générer tous les enregistrements initiaux avant la limite inférieure même s'il n'en a pas besoin.
Notez que ROW_NUMBER est un bigint , donc nous ne pouvons pas parcourir 2 ^^ 64 (== 16 ^^ 16) enregistrements générés avec une méthode qui l'utilise. Cette requête respecte donc la même limite supérieure sur les valeurs générées.
la source
Cela utilise un code procédural et une fonction table. Lent, mais facile et prévisible.
Usage:
C'est une table, vous pouvez donc l'utiliser en jointure avec d'autres données. J'utilise le plus souvent cette fonction comme côté gauche d'une jointure contre une heure, un jour, etc. GROUP BY pour assurer une séquence contiguë de valeurs de temps.
Les performances sont sans intérêt (16 secondes pour un million de lignes) mais suffisantes pour de nombreuses raisons.
la source
Oracle 12c; Rapide mais limité:
Remarque : limité au nombre de lignes de la vue all_objects;
la source
La solution que j'ai développée et utilisée depuis un certain temps maintenant (chevauchant certains sur les œuvres partagées d'autres) est légèrement similaire à au moins une publiée. Il ne fait référence à aucune table et renvoie une plage non triée allant jusqu'à 1048576 valeurs (2 ^ 20) et peut inclure des négatifs si vous le souhaitez. Vous pouvez bien sûr trier le résultat si nécessaire. Il fonctionne assez rapidement, en particulier sur les plus petites plages.
la source
la source
J'ai créé la fonction ci-dessous après avoir lu ce fil. Simple et rapide:
la source