Reputation: 237
I realize SQL is not the best language for this, but this is a homework assignment to write a function that will take an argument N and will find the prime numbers (N=10,000,000) between 1 and 10 million. I am using Postgresql. Here is my attempt:
--First create table Numbers with all numbers from 1 to 10000000 in it
create table numbers(number bigint);
--Use this function to fill it in:
create or replace function populate(top bigint) RETURNS void as $$
declare
i bigint:=1;
begin
while(i<=top) LOOP
insert into numbers(number)
values(i);
i:=i+1;
END LOOP;
END; $$ LANGUAGE plpgsql;
--Function primes that returns all primes up to N
create or replace function primes(N bigint) RETURNS void AS $$
DECLARE
first bigint :=3;
last bigint :=2;
BEGIN
--create table t1 and insert all odd integers from 3 to N (and 2)
create table t1(a bigint);
INSERT into t1(a)
select number
from numbers
where (number%2 <> 0 or number = 2)
AND number<=N AND number<>1;
--Use Sieve of Erastothenes to find primes
while (last < sqrt(n)) LOOP
first:= (select * from t1 where a>last order by a limit 1);
last:= first* first;
--delete from list of primes all multiples of the primes in the range of first-last
-- (first run-through is primes in range of 3-9, second run-through would be primes in range of 11-121, etc.)
delete from t1
where a in (select n1.number * t.a
from t1 as t
inner join numbers as n1
on n1.number >= t.a
and n1.number<= n/t.a
where t.a>=first
and t.a<last);
END LOOP;
END; $$ LANGUAGE plpgsql;
Upvotes: 1
Views: 2443
Reputation: 194
I don't think anyone actually checks or compares most of these postings - I've posted a couple of poor runners just to find out, but nobody called them. If you are inclined to compare though, you'll find this readable and fast:
IF (SELECT OBJECT_ID ('tempdb.dbo.#Numbers')) IS NOT NULL
DROP TABLE #Numbers;
CREATE TABLE #Numbers (Prime INT NOT NULL, Squared BIGINT PRIMARY KEY CLUSTERED);
DECLARE @MaxPrime INT = 1000000;
;WITH
GroupingDriver AS
(
SELECT CAST('7' AS BIGINT) as Interval
UNION ALL
SELECT Interval+30
FROM GroupingDriver
WHERE Interval+30 < @MaxPrime
)
INSERT INTO #Numbers
SELECT 2 AS 'Number', 4 AS 'SquareNo'
UNION ALL
SELECT 3 AS 'Number', 9 AS 'SquareNo'
UNION ALL
SELECT 5 AS 'Number', 25 AS 'SquareNo'
UNION ALL
SELECT Prime.Number, Prime.Number * Prime.Number
FROM GroupingDriver
CROSS APPLY ( VALUES (GroupingDriver.Interval),
(GroupingDriver.Interval+4),
(GroupingDriver.Interval+6),
(GroupingDriver.Interval+10),
(GroupingDriver.Interval+12),
(GroupingDriver.Interval+16),
(GroupingDriver.Interval+22),
(GroupingDriver.Interval+24) ) AS Prime(Number)
WHERE Prime.Number < @MaxPrime
OPTION (MAXRECURSION 0);
Now remove those divisible by other primes. We just used squared as a cutoff point for comparison.
SELECT Prime
FROM #Numbers n
WHERE NOT EXISTS (SELECT 1
FROM #Numbers AS p
WHERE p.Squared <= n.Prime
AND n.Prime % p.Prime = 0);
GO
Upvotes: 0
Reputation: 6255
A good review of the topic is here: https://sqlserverfast.com/blog/hugo/2006/09/the-prime-number-challenge-great-waste-of-time/
But for a homework problem, you should do your own work.
Upvotes: 1