Ich hatte mit vor Jahren beschäftigen, so dachte ich, die schnellste/einfachste Art und Weise heraus, ob Ihre Datenbank eine Tabelle mit mehreren Datensätzen hat, als Sie zählen müssen.
Erstens, trotz der Vorschläge müssen Sie nicht eine Tabelle von Datensätzen "erstellen" ... alles, was Sie brauchen, ist "ANY" -Tabelle, die bereits Datensätze hat. Solange die Tabelle mehr Datensätze enthält, als Sie zählen müssen, sind Sie gut.
SELECT top (5) ROW_NUMBER() OVER(Order by [Primary_Key] desc) AS Integer
FROM SOME_TABLE --that has more than 5 rows.
AUCH dies ist die elegante (Mathe) Art und Weise. Wo Sie keine große Tabelle bereits in der Datenbank haben.
Verwenden Sie die Split-Rekursion, mit der Sie eine Tabelle mit bis zu 2^n-1 ganzen Zahlen erzeugen können, wobei n die Rekursionsgrenze ist. Plus dies ist vollständig parametriert, so dass es leicht in Funktion gesetzt werden kann
DECLARE @n int, @cnt int;
set @cnt = 5;
SET @n = LOG(@cnt)/LOG(2) +1; --use change of base to find LOG base 2
WITH Num AS (
SELECT @n [Value]
UNION ALL
SELECT [Value] - 1
FROM Num
WHERE [Value] > 1
UNION ALL
SELECT [Value] - 1
FROM Num
WHERE [Value] > 1
)
SELECT * from (
SELECT ROW_NUMBER() OVER(Order by Value asc) AS [Integer]
FROM Num
)i
where [Integer] <= @cnt
Der einzige Nachteil ist, dass es doppelt so viele Datensätze erzeugen kann wie während Rekursion benötigt, so hat es das Potenzial für mehr Overhead als Inline-Rekursion. ABER vermeidet dadurch vollständig die Rekursionsgrenze. (Sie sollten nicht immer eine Notwendigkeit, die ersten 2^100-1 ganze Zahlen aufzulisten.) (Auch vorhersagen, ich werde einfach Sie mit so viel Festplattenspeicher keinen Computer haben.)
Diese Nachteil ist, warum ich die nächste Funktion erstellt habe. Dieselbe Doubling-Technik wie die Split-Rekursion, aber innerhalb einer While-Schleife. UND das letzte Mal, es läuft nur die notwendigen Datensätze nicht doppelt. Mit dieser Funktion können Sie auch einen Bereich angeben und alle Zahlen in diesem Bereich mit einem 0-basierten Index dieser Zahlen zurückgeben. Ich habe diese Null-Basis-Spalte als nutzloses Artefakt der Berechnung betrachtet, aber es hat sich als äußerst hilfreich erwiesen, sowohl den Bereich als auch den Index in einer Zeile zu haben.
create function [dbo].[fn_Integers]
(
@Min_Integer int = 1
,@Max_Integer int
)
RETURNS @retTable TABLE
([BASE] int identity(0,1)
,[INTEGER] int)
AS
BEGIN
Declare @RANGE int
SET @RANGE = @[email protected]_Integer
insert into @retTable
select NULL --initial value for recursion
While ((SELECT MAX([BASE]) FROM @retTable r) < @RANGE)
BEGIN
INSERT into @retTable
select [INTEGER] from @retTable r
where [BASE] < (SELECT @RANGE - MAX([BASE]) FROM @retTable r)
END
Update @retTable set
[INTEGER] = [BASE] + @Min_Integer
RETURN
END
GO
kann es etwa 50000 Zahlen pro Sekunde tun (auf meinem Arbeitsplatz) und Ausgabe sieht wie folgt
SELECT * FROM [fn_Integers](18,50000)
BASE INTEGER
-----------------
0 18
1 19
2 20
...
49982 50000
Klingt verrückt, aber Tabellen von Zahlen speichern Schleife viel Zeit, die oft effizienter ist. – u07ch
Dies ist der Gewinner. Die Daten, die ich durchlaufe, haben Millionen von Zeilen, und ich muss diese Art von Operation pro Zeile ausführen. Dies ist eine sehr gute Lösung – Turbo