Recientemente, me dieron la tarea de imprimir todos los números primos (1-100). Fallé drásticamente allí. Mi código:
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;
)
ENDAunque terminé sin completarlo, me pregunto si es factible hacer dichos programas en la base de datos (SQL Server 2008 R2).
En caso afirmativo, cómo puede terminar.
                    
                        sql-server
                                sql-server-2008-r2
                                t-sql
                                
                    
                    
                        ispostback
fuente
                
                fuente

Respuestas:
Con mucho, la forma más rápida y fácil de imprimir "todos los números primos (1-100)" es aceptar plenamente el hecho de que los números primos son un conjunto de valores conocido, finito e inmutable ("conocido" y "finito" dentro de un rango particular, por supuesto). A esta pequeña escala, ¿por qué desperdiciar CPU cada vez para calcular un montón de valores que se conocen desde hace mucho tiempo, y apenas ocupa memoria para almacenar?
Por supuesto, si necesita calcular los números primos entre 1 y 100, lo siguiente es bastante eficiente:
Esta consulta solo prueba números impares ya que los números pares no serán primos de todos modos. También es específico para el rango de 1 a 100.
Ahora, si necesita un rango dinámico (similar a lo que se muestra en el código de ejemplo en la pregunta), la siguiente es una adaptación de la consulta anterior que aún es bastante eficiente (calculó el rango de 1 - 100,000 - 9592 entradas - en menos de 1 segundo):
Mi prueba (usando
SET STATISTICS TIME, IO ON;) muestra que esta consulta funciona mejor que las otras dos respuestas dadas (hasta ahora):ALCANCE: 1-100
ALCANCE: 1 - 10,000
ALCANCE: 1 - 100,000
ALCANCE: 99,900 - 100,000
NOTA : Para ejecutar esta prueba, tuve que corregir un error en el código de Dan;
@startnumno se incluyó en la consulta, por lo que siempre comenzó en1. Reemplacé laDividend.num <= @endnumlínea conDividend.num BETWEEN @startnum AND @endnum.ALCANCE: 1 - 100,000 (nueva prueba parcial)
Después de arreglar la consulta de Dan para la prueba 99,900 - 100,000, noté que no había más lecturas lógicas en la lista. Así que volví a probar este rango con esa corrección aún aplicada y descubrí que las lecturas lógicas habían desaparecido nuevamente y los tiempos eran ligeramente mejores (y sí, se devolvió el mismo número de filas).
fuente
ROW_NUMBER() OVER (ORDER BY (SELECT 1))? ¿NoROW_NUMBER() OVER ()sería equivalente?OVER (), obtendrá el siguiente error:The function 'ROW_NUMBER' must have an OVER clause with ORDER BY.. Y, conORDER BY, no puede ser una constante, de ahí la subconsulta para devolver una constante.DECLARE @RangeStart INT = 999900, @RangeEnd INT = 1000000;funciona pero tan pronto como lo configuroDECLARE @RangeStart INT = 9999999900, @RangeEnd INT = 10000000000;diceMsg 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. El valor máximo queINTpuede contener es 2,147,483,647, que es menor que su valor inicial de 9,999,999,900. Obtiene ese error incluso si ejecuta solo elDECLARE. Puede intentar cambiar los tipos de datos variables para que seanBIGINTy ver cómo funciona. Es posible que se necesiten otros cambios menores para respaldar eso. Para los rangos de tipo de datos, consulte: int, bigint, smallint y tinyint .Sería una forma simple pero no muy eficiente de devolver los números primos en el rango 2-100 (1 no es primo)
También podría materializar los números del 2 al 100 en una tabla e implementar el Tamiz de Eratóstenes mediante actualizaciones o eliminaciones repetidas.
fuente
Sí, es factible, pero no creo que T-SQL sea la herramienta adecuada para el trabajo. A continuación se muestra un ejemplo de un enfoque basado en conjuntos en T-SQL para este problema.
fuente
Podemos escribir el siguiente código y funciona:
Arriba he creado un Procedimiento almacenado para obtener números primos.
Para conocer los resultados, ejecute el procedimiento almacenado:
fuente
fuente