Récemment, on m'a confié la tâche d'imprimer tous les nombres premiers (1-100). J'ai échoué radicalement là-bas. Mon 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
Bien que je me sois retrouvé sans le terminer, je me demande s'il est possible de faire de tels programmes sur la base de données (SQL Server 2008 R2).
Si oui, comment cela peut se terminer.
sql-server
sql-server-2008-r2
t-sql
ispostback
la source
la source
Réponses:
La manière de loin la plus rapide et la plus simple d’ imprimer «tous les nombres premiers (1-100)» consiste à adopter pleinement le fait que les nombres premiers sont un ensemble de valeurs connues, finies et immuables («connues» et «finies» au sein d’une gamme particulière, bien sûr). À cette petite échelle, pourquoi gaspiller le CPU à chaque fois pour calculer un tas de valeurs connues depuis très longtemps et prendre peu de mémoire pour stocker?
Bien sûr, si vous devez calculer les nombres premiers entre 1 et 100, ce qui suit est assez efficace:
Cette requête ne teste que les nombres impairs car les nombres pairs ne seront de toute façon pas premiers. Il est également spécifique à la plage de 1 à 100.
Maintenant, si vous avez besoin d'une plage dynamique (similaire à ce qui est montré dans l'exemple de code dans la question), alors ce qui suit est une adaptation de la requête ci-dessus qui est encore assez efficace (elle a calculé la plage de 1 - 100 000 - 9592 entrées - en un peu moins d'une seconde):
Mes tests (en utilisant
SET STATISTICS TIME, IO ON;
) montrent que cette requête fonctionne mieux que les deux autres réponses données (jusqu'à présent):GAMME: 1 - 100
GAMME: 1-10 000
GAMME: 1 - 100 000
GAMME: 99 900 - 100 000
REMARQUE : Afin d'exécuter ce test, j'ai dû corriger un bogue dans le code de Dan -
@startnum
n'était pas pris en compte dans la requête, donc il a toujours commencé à1
. J'ai remplacé laDividend.num <= @endnum
ligne parDividend.num BETWEEN @startnum AND @endnum
.GAMME: 1 - 100 000 (re-test partiel)
Après avoir corrigé la requête de Dan pour le test 99,900 - 100,000, j'ai remarqué qu'il n'y avait plus de lectures logiques répertoriées. J'ai donc retesté cette plage avec ce correctif toujours appliqué et j'ai constaté que les lectures logiques avaient à nouveau disparu et que les temps étaient légèrement meilleurs (et oui, le même nombre de lignes a été renvoyé).
la source
ROW_NUMBER() OVER (ORDER BY (SELECT 1))
? Ne serait pasROW_NUMBER() OVER ()
équivalent?OVER ()
, vous obtiendrez l'erreur suivante:The function 'ROW_NUMBER' must have an OVER clause with ORDER BY.
. Et, avecORDER BY
, il ne peut pas être une constante, d'où la sous-requête pour renvoyer une constante.DECLARE @RangeStart INT = 999900, @RangeEnd INT = 1000000;
ça marche mais dès que je l'ai misDECLARE @RangeStart INT = 9999999900, @RangeEnd INT = 10000000000;
c'est ditMsg 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
. La valeur maximaleINT
pouvant être maintenue est de 2147483647, ce qui est inférieur à votre valeur de départ de 9999 999 900. Vous obtenez cette erreur même si vous exécutez uniquement leDECLARE
. Vous pouvez essayer de changer les types de données variablesBIGINT
et voir comment cela se passe. Il est possible que d'autres modifications mineures soient nécessaires pour soutenir cela. Pour les plages de types de données, veuillez consulter: int, bigint, smallint et tinyint .Un moyen simple mais pas très efficace de renvoyer les nombres premiers compris entre 2 et 100 (1 n'est pas premier) serait
Vous pouvez également potentiellement matérialiser les nombres 2-100 dans un tableau et implémenter le tamis d'Ératosthène via des mises à jour ou des suppressions répétées.
la source
Oui, c'est faisable mais je ne pense pas que T-SQL soit le bon outil pour le travail. Voici un exemple d'une approche basée sur des ensembles dans T-SQL pour ce problème.
la source
Nous pouvons écrire le code ci-dessous et cela fonctionne:
Ci-dessus, j'ai créé une procédure stockée pour obtenir des nombres premiers.
Pour connaître les résultats, exécutez la procédure stockée:
la source
la source