У меня было решение, похожее на решение Ларну, но я пошел на собрание и не хотел, чтобы оно пропало даром.Он генерирует 1229 простых чисел (все простые числа меньше 10 000) за 7 секунд.
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 секунду, чтобы найти все простые числа ниже 10K, но идет до 2,5 минут, чтобы получить все простые числа ниже 100K (9592 простых чисел).
РЕДАКТИРОВАТЬ 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