Kürzlich wurde mir die Aufgabe übertragen, alle Primzahlen (1-100) zu drucken. Ich habe dort drastisch versagt. Mein Code:
Create Procedure PrintPrimeNumbers
@startnum int,
@endnum int
AS
BEGIN
Declare @a INT;
Declare @i INT = 1
(
Select a = @startnum / 2;
WHILE @i<@a
BEGIN
@startnum%(@a-@i)
i=i+1;
)
END
Obwohl ich es nicht abgeschlossen habe, frage ich mich, ob es möglich ist, solche Programme in einer Datenbank (SQL Server 2008 R2) auszuführen.
Wenn ja, wie kann es enden?
sql-server
sql-server-2008-r2
t-sql
ispostback
quelle
quelle
Antworten:
Der mit Abstand schnellste und einfachste Weg, "alle Primzahlen (1-100)" zu drucken, besteht darin, die Tatsache vollständig zu berücksichtigen, dass Primzahlen eine bekannte, endliche und unveränderliche Menge von Werten sind ("bekannt" und "endlich" innerhalb von a besondere Reichweite natürlich). Warum sollten Sie in diesem kleinen Maßstab jedes Mal CPU verschwenden, um eine Reihe von Werten zu berechnen, die seit langem bekannt sind, und kaum Speicherplatz zum Speichern benötigen?
Wenn Sie die Primzahlen zwischen 1 und 100 berechnen müssen, ist Folgendes natürlich ziemlich effizient:
Diese Abfrage testet nur ungerade Zahlen, da gerade Zahlen sowieso keine Primzahlen sind. Es ist auch spezifisch für den Bereich von 1 bis 100.
Wenn Sie nun einen Dynamikbereich benötigen (ähnlich wie im Beispielcode in der Frage gezeigt), ist das Folgende eine Anpassung der obigen Abfrage, die immer noch ziemlich effizient ist (sie hat den Bereich von 1 - 100.000 - 9592 berechnet Einträge - in knapp 1 Sekunde):
Meine Tests (mit
SET STATISTICS TIME, IO ON;
) zeigen, dass diese Abfrage eine bessere Leistung erbringt als die beiden anderen Antworten (bisher):BEREICH: 1 - 100
BEREICH: 1 - 10.000
BEREICH: 1 - 100.000
BEREICH: 99.900 - 100.000
HINWEIS : Um diesen Test auszuführen, musste ich einen Fehler in Dans Code beheben -
@startnum
wurde in der Abfrage nicht berücksichtigt, sodass er immer bei begann1
. Ich habe dieDividend.num <= @endnum
Leitung durch ersetztDividend.num BETWEEN @startnum AND @endnum
.BEREICH: 1 - 100.000 (teilweiser erneuter Test)
Nachdem ich Dans Abfrage für den 99.900 - 100.000 Test korrigiert hatte, stellte ich fest, dass keine logischen Lesevorgänge mehr aufgeführt waren. Also habe ich diesen Bereich erneut getestet, wobei der Fix noch angewendet wurde, und festgestellt, dass die logischen Lesevorgänge wieder weg waren und die Zeiten etwas besser waren (und ja, die gleiche Anzahl von Zeilen wurde zurückgegeben).
quelle
ROW_NUMBER() OVER (ORDER BY (SELECT 1))
? Wäre nichtROW_NUMBER() OVER ()
gleichwertig?OVER ()
, erhalten Sie die folgende Fehlermeldung :The function 'ROW_NUMBER' must have an OVER clause with ORDER BY.
. Und mitORDER BY
kann es keine Konstante sein, daher die Unterabfrage, eine Konstante zurückzugeben.DECLARE @RangeStart INT = 999900, @RangeEnd INT = 1000000;
, aber sobald ich es einstelle, stehtDECLARE @RangeStart INT = 9999999900, @RangeEnd INT = 10000000000;
esMsg 8115, Level 16, State 2, Line 1 Arithmetic overflow error converting expression to data type int. Msg 1014, Level 15, State 1, Line 5 A TOP or FETCH clause contains an invalid value.
?INT
. Der maximale Wert, derINT
halten kann, ist 2.147.483.647, was kleiner als Ihr Startwert von 9.999.999.900 ist. Sie erhalten diesen Fehler auch dann, wenn Sie nur das ausführenDECLARE
. Sie können versuchen, die variablen Datentypen zu ändernBIGINT
und zu sehen, wie das geht. Es ist möglich, dass weitere geringfügige Änderungen erforderlich sind, um dies zu unterstützen. Informationen zu Datentypbereichen finden Sie unter: int, bigint, smallint und tinyint .Eine einfache, aber nicht sehr effiziente Möglichkeit, die Primzahlen im Bereich von 2 bis 100 (1 ist keine Primzahl) zurückzugeben, wäre
Sie können möglicherweise auch die Zahlen 2-100 in einer Tabelle materialisieren und das Sieb des Eratosthenes durch wiederholte Aktualisierungen oder Löschungen implementieren .
quelle
Ja, das ist machbar, aber ich denke nicht, dass T-SQL das richtige Werkzeug für diesen Job ist. Unten finden Sie ein Beispiel für einen satzbasierten Ansatz in T-SQL für dieses Problem.
quelle
Wir können den folgenden Code schreiben und es funktioniert:
Oben habe ich eine gespeicherte Prozedur erstellt, um Primzahlen zu erhalten.
Führen Sie die gespeicherte Prozedur aus, um die Ergebnisse zu erfahren:
quelle
quelle