我有一个整数表
number
--------
104723
104729
9998
448
目标是找到一组数字中最大的素数。我已经使用以下程序
完成了这项工作Declare @t table(number int)
Insert into @t values(104723),(104729),(9998),(448)
Declare @maxNum INT
SELECT @maxNum = MAX(number) FROM @t
--generate a number table from 2 to the maximum number supplied
;WITH Cte AS (
SELECT 2 AS num
UNION ALL
SELECT num+1
FROM cte
WHERE num<@maxNum)
SELECT TOP(1) num AS 'Largest Prime' FROM cte
--filter by some known prime numbers (keeping the range between 2 to 19
WHERE
(num=2 OR num%2!=0) AND
(num=3 OR num%3!=0) AND
(num=5 OR num%5!=0) AND
(num=7 OR num%7!=0) AND
(num=11 OR num%11!=0) AND
(num=13 OR num%13!=0) AND
(num=17 OR num%17!=0) AND
(num=19 OR num%19!=0)
ORDER BY 1 DESC
OPTION (MAXRECURSION 0)
/*
Largest Prime
-------------
104729
*/
但我相信会有更好的方法。我怎样才能优化它?
答案 0 :(得分:2)
我修改了一下你的查询:
DECLARE @t TABLE (number int)
INSERT INTO @t VALUES
(104723),(104729),(9998),(448)
DECLARE @maxNum int
SELECT @maxNum = MAX(number)
FROM @t
;WITH cte AS (
SELECT 2 AS num
UNION ALL
SELECT num+1
FROM cte
WHERE num < @maxNum
)
SELECT MAX(number) as LargestPrime
FROM (
SELECT number
FROM @t t
CROSS JOIN Cte c
WHERE t.number%c.num=0
GROUP BY number
HAVING COUNT(num) = 1
) as t
OPTION (MAXRECURSION 0)
这将带来@t
表中最大的素数:
LargestPrime
104729
主要思想是获得最大数量,建立CTE,数字从2到最大。然后进行笛卡尔联接,这样我们就可以尝试从@t
和CTE中获取每个数字的modulo。如果有数字的模数> 0
超过1次 - 它们不是素数。
答案 1 :(得分:1)
略有不同的方法。
填写只有素数的表格。
然后只需将表连接到素数上并返回最大值
declare @T table (number int primary key);
insert into @T values (104723),(104729),(9998),(448);
declare @maxNum int;
set @maxNum = (select max(number) from @T);
declare @primes TABLE (n int primary key);
insert into @primes (n) values (2);
with cte as (
SELECT 3 AS n
UNION ALL
SELECT n+2 FROM cte WHERE n+2 <= @maxNum) -- Only uneven numbers lower then @maxNum
insert into @primes (n)
select n from cte
where (n%3 > 0 and n%5 > 0 and n%7 > 0) or n < 8 -- Filter a majority of the non-primes
option (MAXRECURSION 0);
-- Remove the numbers where the modulus by a lower number returns 0
-- Limiting it to the numbers lower or equal to the square root of the number.
-- The idea behind this is that even if the number has a divisor that's higher than the square root, it would mean there also exists a lower divisor.
DELETE p FROM @primes p
WHERE EXISTS (
SELECT 1 FROM @primes AS p1
WHERE p1.n <= CEILING(SQRT(p.n)) and (p.n%p1.n) = 0 and p.n > 8
);
select max(t.number) as LargestPrime
from @T t
inner join @primes p on (t.number = p.n);
当然,如果你经常这样做,那么创建一个包含大量素数的永久表可能是值得的。