「欲しいものを書くだけでいい」というのがSQLのいいところ。この場合は「約数をちょうど2つ持つ整数」と書けばいい。エラトステネスの篩いを試みたりしてはいけない。(そういう意味ではPrologでもいいのだけれど、文法を思い出せない。)
-- 0から9までの数を入れるテーブル create table nums (i integer); -- 0から9までの数を入れる insert into nums (i) values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9); -- 0から99までの数を入れるテーブル(100は素数でない) drop table if exists integers; create table integers select 10*a.i+b.i as n from nums as a, nums as b order by n; -- 素数を表示する select n prime from( select x.n, count(distinct d.n) c from integers x,integers d where mod(x.n,d.n)=0 and d.n<=x.n group by x.n) tmp where c=2 order by prime;
以上
以下は古いバージョン(いろいろやりすぎ)。
SELECT n prime FROM( SELECT x.n,COUNT(DISTINCT d.n) c FROM integers x,integers d WHERE MOD(x.n,d.n)=0 AND d.n<=x.n GROUP BY x.n) tmp WHERE c=2;
あらかじめ整数をテーブルに入れておくという準備が必要で、Oracleならこんな感じか。
DROP TABLE integers; CREATE TABLE integers (n INT NOT NULL); DECLARE maxNum INT:=100; i INT:=1; BEGIN EXECUTE IMMEDIATE 'TRUNCATE TABLE integers'; WHILE i<maxNum LOOP INSERT INTO integers (n) VALUES (i); i:=i+1; END LOOP; END; / SELECT n prime FROM( SELECT x.n,COUNT(DISTINCT d.n) c FROM integers x,integers d WHERE MOD(x.n,d.n)=0 AND d.n<=x.n GROUP BY x.n) tmp WHERE c=2;
SELECT文を直接書けないからPL/SQLはあまり好きではないんだけど、
無理矢理PROCEDUREにするなら、こんな感じか。
CREATE OR REPLACE PROCEDURE primes (maxNum INT) AS i INT:=1; CURSOR cur IS SELECT n prime FROM( SELECT x.n,COUNT(DISTINCT d.n) c FROM integers x,integers d WHERE MOD(x.n,d.n)=0 AND d.n<=x.n GROUP BY x.n) tmp WHERE c=2; BEGIN EXECUTE IMMEDIATE 'TRUNCATE TABLE integers'; WHILE i<maxNum LOOP INSERT INTO integers (n) VALUES (i); i:=i+1; END LOOP; FOR item IN cur LOOP DBMS_OUTPUT.PUT_LINE(item.prime); END LOOP; END; / CALL primes(100);
Version 5になってやっと使えるようになったMySQLのストアド・プロシージャを使うなら。
DELIMITER // DROP TABLE IF EXISTS integers// CREATE TABLE integers (n INT)// DROP PROCEDURE IF EXISTS primes// CREATE PROCEDURE primes(maxNum INT) BEGIN DECLARE i INT DEFAULT 1; TRUNCATE table integers; WHILE i<maxNum DO INSERT INTO integers (n) VALUES (i); SET i=i+1; END WHILE; SELECT n prime FROM( SELECT x.n,COUNT(DISTINCT d.n) c FROM integers x,integers d WHERE MOD(x.n,d.n)=0 AND d.n<=x.n GROUP BY x.n) tmp WHERE c=2; END;// CALL primes(100)//
追記:エラトステネスの篩いね、そりゃあ、このほうが速いよ。
DELIMITER // DROP TABLE IF EXISTS integers// CREATE TABLE integers ( n INT PRIMARY KEY, flag INT DEFAULT 0 NOT NULL, KEY(flag) )// DROP TABLE IF EXISTS results// CREATE TABLE results (prime INT PRIMARY KEY)// DROP PROCEDURE IF EXISTS primes// CREATE PROCEDURE primes(maxNum INT) BEGIN DECLARE i INT DEFAULT 2; TRUNCATE table integers; WHILE i<maxNum DO INSERT INTO integers (n) VALUES (i); SET i=i+1; END WHILE; WHILE EXISTS (SELECT * FROM integers WHERE flag=0) DO INSERT INTO results (prime) SELECT n FROM integers WHERE flag=0 LIMIT 1; UPDATE integers JOIN (SELECT MAX(prime) p FROM results) tmp SET flag=1 WHERE MOD(n,p)=0; END WHILE; SELECT prime FROM results; END;// CALL primes(100)//
なにこれ?
タイトルのとおり、「100までの素数を列記する方法」です