Ich habe zwei Zahlen als Eingabe vom Benutzer, wie zum Beispiel 1000
und 1050
.
Wie generiere ich die Zahlen zwischen diesen beiden Zahlen mithilfe einer SQL-Abfrage in separaten Zeilen? Ich will das:
1000
1001
1002
1003
.
.
1050
sql
sql-server
tsql
sql-server-2008
user3211705
quelle
quelle
Eine alternative Lösung ist der rekursive CTE:
quelle
Demo
Beachten Sie, dass diese Tabelle maximal 2048 enthält, da die Zahlen dann Lücken aufweisen.
Hier ist ein etwas besserer Ansatz mit einer Systemansicht (seit SQL-Server 2005):
Demo
oder verwenden Sie eine benutzerdefinierte Zahlentabelle. Dank an Aaron Bertrand empfehle ich, den gesamten Artikel zu lesen: Generieren Sie einen Satz oder eine Sequenz ohne Schleifen
quelle
WHERE type = 'P'
und vermeidenSELECT DISTINCT
String index out of range: 33
Ich habe kürzlich diese Inline-Tabellenwertfunktion geschrieben, um genau dieses Problem zu lösen. Die Reichweite ist nicht auf Speicher und Speicher beschränkt. Es greift auf keine Tabellen zu, sodass im Allgemeinen keine Lese- oder Schreibvorgänge auf der Festplatte erforderlich sind. Es fügt bei jeder Iteration exponentiell Verknüpfungswerte hinzu, sodass es auch für sehr große Bereiche sehr schnell ist. Auf meinem Server werden in fünf Sekunden zehn Millionen Datensätze erstellt. Es funktioniert auch mit negativen Werten.
Es ist auch praktisch für Datums- und Zeitbereiche:
Sie können einen Cross-Apply-Join verwenden, um Datensätze basierend auf den Werten in der Tabelle aufzuteilen. Um beispielsweise einen Datensatz für jede Minute in einem Zeitbereich in einer Tabelle zu erstellen, können Sie Folgendes tun:
quelle
SELECT X FROM fn_ConsecutiveNumbers(5, 500) ORDER BY X;
Die beste Option, die ich verwendet habe, ist wie folgt:
Ich habe damit Millionen von Datensätzen generiert und es funktioniert perfekt.
quelle
Es funktioniert für mich!
quelle
sys.all_objects
- für kleine Bereiche <2000 Elemente ist dies kein Problem. Sie sind sich nicht sicher, ob es Berechtigungsprobleme geben wird? Perfekt, um schnell eine Reihe von Testdaten zu generieren.select top 50 ROW_NUMBER() over(order by a.name) + 1000 as Rcount from sys.all_objects a, sys.all_objects b
. Wo ich vorher nur 2384 Zeilen generieren konnte, kann ich jetzt 5683456 Zeilen generieren.Der beste Weg ist die Verwendung von rekursiven ctes.
Saludos.
quelle
quelle
Wenn Sie keine Probleme beim Installieren einer CLR-Assembly auf Ihrem Server haben, empfiehlt es sich, eine Tabellenwertfunktion in .NET zu schreiben. Auf diese Weise können Sie eine einfache Syntax verwenden, die das Verknüpfen mit anderen Abfragen erleichtert und als Bonus keinen Speicher verschwendet, da das Ergebnis gestreamt wird.
Erstellen Sie ein Projekt mit der folgenden Klasse:
Legen Sie die Assembly irgendwo auf dem Server ab und führen Sie Folgendes aus:
Jetzt können Sie ausführen:
quelle
Nichts Neues, aber ich habe die Brian Pressler-Lösung umgeschrieben, um das Auge zu schonen. Sie könnte für jemanden nützlich sein (auch wenn es nur meine Zukunft ist):
quelle
ROW_NUMBER()
, haben dieses Problem nicht.2 Jahre später, aber ich stellte fest, dass ich das gleiche Problem hatte. Hier ist, wie ich es gelöst habe. (bearbeitet, um Parameter einzuschließen)
quelle
Die Antwort von slartidan kann in Bezug auf die Leistung verbessert werden, indem alle Verweise auf das kartesische Produkt entfernt und
ROW_NUMBER()
stattdessen verwendet werden ( Ausführungsplan verglichen ):Wickeln Sie es in einen CTE ein und fügen Sie eine where-Klausel hinzu, um die gewünschten Zahlen auszuwählen:
quelle
SELECT ROW_NUMBER() OVER (...) - 1 AS n
. In einigen Fällen kann dies die Leistung beeinträchtigen.Hier sind einige recht optimale und kompatible Lösungen:
quelle
select
ingwhere spt_values.number between @min and @max
?Ich weiß, dass ich 4 Jahre zu spät bin, aber ich bin auf eine weitere alternative Antwort auf dieses Problem gestoßen. Das Problem der Geschwindigkeit ist nicht nur das Vorfiltern, sondern auch das Verhindern des Sortierens. Es ist möglich, die Verknüpfungsreihenfolge so zu erzwingen, dass das kartesische Produkt als Ergebnis der Verknüpfung tatsächlich zählt. Slartidans Antwort als Ausgangspunkt verwenden:
Wenn wir den gewünschten Bereich kennen, können wir ihn über @Upper und @Lower angeben. Durch Kombinieren des Join-Hinweises REMOTE mit TOP können wir nur die Teilmenge der gewünschten Werte berechnen, ohne dass etwas verschwendet wird.
Der Join-Hinweis REMOTE zwingt den Optimierer, zuerst auf der rechten Seite des Joins zu vergleichen. Wenn Sie jeden Join als FERN vom höchsten bis zum niedrigstwertigen Wert angeben, zählt der Join selbst korrekt um eins nach oben. Sie müssen nicht mit einem WHERE filtern oder mit einem ORDER BY sortieren.
Wenn Sie den Bereich vergrößern möchten, können Sie weitere Verknüpfungen mit zunehmend höheren Größenordnungen hinzufügen, sofern diese in der FROM-Klausel von der höchsten zur niedrigsten Bedeutung geordnet sind.
Beachten Sie, dass dies eine Abfrage ist, die für SQL Server 2008 oder höher spezifisch ist.
quelle
Dies wird auch reichen
quelle
Die beste Geschwindigkeit beim Ausführen von Abfragen
quelle
rekursiver CTE in exponentieller Größe (selbst bei einer Standardrekursion von 100 können bis zu 2 ^ 100 Zahlen erstellt werden):
quelle
@startnum
undendnum
sollte vom Benutzer eingegeben werden?Ich musste den Bilddateipfad mit einer ähnlichen Methode in die Datenbank einfügen. Die folgende Abfrage hat gut funktioniert:
Der Code für Sie wäre:
quelle
Das mache ich, es ist ziemlich schnell und flexibel und nicht viel Code.
Beachten Sie, dass (ORDER BY @count) ein Dummy ist. Es macht nichts anderes als ROW_NUMBER () erfordert ein ORDER BY.
Bearbeiten : Ich erkannte, dass die ursprüngliche Frage war, einen Bereich von x bis y zu erhalten. Mein Skript kann folgendermaßen geändert werden, um einen Bereich zu erhalten:
quelle
quelle
Dies funktioniert nur für Sequenzen, solange eine Anwendungstabelle Zeilen enthält. Angenommen, ich möchte eine Sequenz von 1..100 und habe die Anwendungstabelle dbo.foo mit der Spalte (vom numerischen oder Zeichenfolgentyp) foo.bar:
Trotz des Vorhandenseins in einer order by-Klausel muss dbo.foo.bar keine eindeutigen oder gar nicht null Werte haben.
Natürlich verfügt SQL Server 2012 über Sequenzobjekte, daher gibt es in diesem Produkt eine natürliche Lösung.
quelle
Folgendes habe ich mir ausgedacht:
Erzeugt bis zu 2 ^ 24 Werte. Join-Bedingungen halten es für kleine Werte schnell.
quelle
Dies war für mich in 36 Sekunden auf unserem DEV-Server erledigt. Wie bei Brians Antwort ist es wichtig, sich innerhalb der Abfrage auf das Filtern nach dem Bereich zu konzentrieren. a ZWISCHEN versucht immer noch, alle anfänglichen Datensätze vor der Untergrenze zu generieren, obwohl sie nicht benötigt werden.
Beachten Sie, dass ROW_NUMBER ein Bigint ist , sodass wir mit keiner Methode, die es verwendet, über 2 ^^ 64 (== 16 ^^ 16) generierte Datensätze gehen können. Diese Abfrage berücksichtigt daher die gleiche Obergrenze für generierte Werte.
quelle
Dies verwendet prozeduralen Code und eine Tabellenwertfunktion. Langsam, aber einfach und vorhersehbar.
Verwendung:
Es ist eine Tabelle, sodass Sie sie in Verknüpfungen mit anderen Daten verwenden können. Ich verwende diese Funktion am häufigsten als linke Seite eines Joins gegen eine GROUP BY-Stunde, einen Tag usw., um eine zusammenhängende Folge von Zeitwerten sicherzustellen.
Die Leistung ist wenig inspirierend (16 Sekunden für eine Million Zeilen), aber für viele Zwecke gut genug.
quelle
Oracle 12c; Schnell aber begrenzt:
Hinweis : Beschränkt auf die Zeilenanzahl der Ansicht all_objects.
quelle
Die Lösung, die ich seit einiger Zeit entwickelt und verwendet habe (einige davon basieren auf den gemeinsamen Werken anderer), ähnelt mindestens einer veröffentlichten. Es verweist nicht auf Tabellen und gibt einen unsortierten Bereich von bis zu 1048576 Werten (2 ^ 20) zurück und kann bei Bedarf auch Negative enthalten. Sie können das Ergebnis natürlich bei Bedarf sortieren. Es läuft ziemlich schnell, besonders auf kleineren Reichweiten.
quelle
quelle
Ich habe die folgende Funktion ausgeführt, nachdem ich diesen Thread gelesen habe. Einfach und schnell:
quelle