sql-server SQL Server中的前1000个素数

p5fdfcr1  于 2022-10-31  发布在  SQL Server
关注(0)|答案(4)|浏览(225)

我得到了Prime的程序,它只给出2作为输出。它应该给我所有基于我写的Java程序。
这是我为质数创建的SQL。它在SQL Server中。我想打印前1000个质数。你能告诉我这段代码中的问题吗?

DECLARE @i INT = 1
    DECLARE @j INT = 2
    DECLARE @COUNT INT
    BEGIN
    WHILE @j <= 10
        BEGIN
            SET @COUNT = 0
            WHILE @i <= @j
                BEGIN
                    BEGIN
                        IF((@j % @i) = 0)
                            SET @COUNT += 1
                    END
                    SET @i += 1
                END
            BEGIN
                IF (@COUNT = 2)
                    PRINT @j
            END
            SET @j += 1
        END
    END
    ;

谢谢你们!

yebdmbv4

yebdmbv41#

为了好玩(我觉得我可能已经回答了某人的家庭作业,但是嘿...),就像一个说,一个计数会快得多:

WITH N AS (
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1, N N2, N N3), --1,000 Numbers
Remainders AS(
    SELECT T1.I AS [Integer],
           T2.I AS Divider,
           T1.I % T2.I AS Remainder
    FROM Tally T1
         JOIN Tally T2 ON T1.I >= T2.I)
SELECT R.[Integer] AS PrimeNumber
FROM Remainders R
GROUP BY R.[Integer]
HAVING COUNT(CASE WHEN R.Remainder = 0 THEN 1 END) <= 2
ORDER BY R.[Integer];

当您对1,000行执行此操作时,速度相当快,但(不出所料)随着范围的增加,执行时间开始呈指数级增加。

aemubtdh

aemubtdh2#

要回答您提出的问题:
你能让我知道这个代码中的问题吗?
您的代码的问题在于,当您迭代到@j的下一个值时,您从未将@i重置回1。

...
        END
        SET @i = 1   --add this line to fix it
        SET @j += 1
        ...
5fjcxozz

5fjcxozz3#

我也有一个类似于Larnu的解决方案,但我参加了一个会议,不想浪费它,它在7秒内产生了1229个素数(所有小于10,000的素数)。

WITH 
E(n) AS(
    SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)
),
E2(n) AS(
    SELECT a.n FROM E a, E b
),
E4(n) AS(
    SELECT a.n FROM E2 a, E2 b
),
cteTally(n) AS(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) n
    FROM E4
)
SELECT n
FROM cteTally t
WHERE (SELECT COUNT(*)
                FROM cteTally i
                WHERE t.n % i.n = 0
                AND i.n < t.n) = 1;

如果允许我们使用一些硬编码的值,它可以运行得更快。

WITH 
E(n) AS(
    SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)
),
E2(n) AS(
    SELECT a.n FROM E a, E b
),
E4(n) AS(
    SELECT a.n FROM E2 a, E2 b
),
cteTally(n) AS(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) n
    FROM E4
)
SELECT *
FROM (VALUES(2),(3),(5),(7))x(n)
UNION ALL
SELECT n
FROM cteTally t
WHERE t.n % 2 <> 0
AND t.n % 3 <> 0 
AND t.n % 5 <> 0 
AND t.n % 7 <> 0 
AND (SELECT COUNT(*)
                FROM cteTally i
                WHERE t.n % i.n = 0
                AND i.n < t.n) = 1;

编辑:最后一个版本需要1秒钟才能找到10 K以下的所有素数,但要想得到100 K以下的所有素数(9592个素数),则要长达2. 5分钟。
编辑2:这里有一个选项,它结合了两个版本来提高大数据集的性能。它也不需要一个大的计数表。

DECLARE @j INT = 1;

CREATE TABLE #Primes( N int);
BEGIN TRY
    BEGIN TRANSACTION;

    WHILE @j <= 1000000
    BEGIN
        INSERT INTO #Primes
        SELECT @J
        FROM #Primes
        WHERE @j % n = 0
        HAVING COUNT(*) <= 1;

        SET @j += 1;
    END;

    COMMIT TRANSACTION;

    SELECT * 
    FROM #Primes
    WHERE N <> 1;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
    THROW;
END CATCH;

DROP TABLE #Primes;
GO
vhmi4jdf

vhmi4jdf4#

这是您自己的代码,位于@Tab阿勒曼提出的解决方案的注解部分,并进行了少量修改,以将结果打印为一个字符串:

DECLARE @i INT = 1
    DECLARE @j INT = 2
    DECLARE @COUNT INT
    DECLARE @PRIME1000 AS VARCHAR(1000)
    BEGIN
    WHILE @j <= 1000
        BEGIN
            SET @COUNT = 0
            WHILE @i <= @j
                BEGIN
                    BEGIN
                        IF((@j % @i) = 0)
                            SET @COUNT += 1
                    END
                    SET @i += 1
                END
            BEGIN
                IF (@COUNT = 2)
                    SET @PRIME1000 = CONCAT_WS(' ', @PRIME1000, @j)
            END
            SET @i = 1
            SET @j += 1
        END
    END;
    PRINT @PRIME1000

相关问题