20211-12-24 用SQL求100以内的质数

遇到一道有意思的题目,使用sql找到100以内的质数

SELECT
    n1.num
FROM
    Numbers2 AS n1
WHERE
    NOT EXISTS(
        SELECT
            *
        FROM
            Numbers2 AS n2
        WHERE
            n2.num > 1
            AND n1.num > n2.num
            AND n1.num % n2.num = 0
    )
    AND n1.num > 1
GROUP BY
    n1.num
ORDER BY
    n1.num;

质数是除了1和它本身,不存在正约数的,大于1的自然数。

大概小学数学的概念,当然,关于它的研究是相当难的。

第一步是构造一个从1到100的数据表,如果生写,比较麻烦,可以用0到9的表搞一个笛卡尔积:

SELECT
    num
FROM
    Numbers
ORDER BY
    num;
/*
 num 
-----
   0
   1
   2
   3
   4
   5
   6
   7
   8
   9
(10 rows)
*/

INSERT INTO
    Numbers2 (num)
SELECT
    (n1.num + n2.num * 10) AS num
FROM
    Numbers n1,
    Numbers n2
ORDER BY
    num;

接着要构造查询语句,思考几个条件:

  1. 质数要大于1。
  2. 在1和其本身之间,没有约数,更进一步,在1和其本身的一半之间,没有约数。

用sql的方法筛选,就需要构造一个这样的表

SELECT
    n1.num AS n1_num,
    n2.num AS n2_num,
    n1.num % n2.num AS n1_n2_mod
FROM
    Numbers2 AS n1,
    Numbers2 AS n2
WHERE
    n2.num > 1
    AND n1.num > n2.num
ORDER BY
    n1.num;

-- n1_num | n2_num | n1_n2_mod 
----------+--------+-----------
--      3 |      2 |         1
--      4 |      2 |         0
--      4 |      3 |         1
--      5 |      2 |         1
--      5 |      3 |         2
--      5 |      4 |         1
--      6 |      2 |         0
--      6 |      3 |         0
--      6 |      4 |         2
--      6 |      5 |         1
--      7 |      2 |         1
--      7 |      3 |         1
--      7 |      4 |         3
--      7 |      5 |         2
--      7 |      6 |         1

然后对n1_num进行GROUP,将表分成若干个集合,只要集合中含余数(n1_n2_mod)为0,则此项n1_num排除。

为了兼顾效率,使用了not exists谓词,其语义是一旦包含约数,立即排除。剩下的就是不包含任何大于1 的正约数的数,也就是质数。

-- num
-------
--   2
--   3
--   5
--   7
--  11
--  13
--  17
--  19
--  23
--  29
--  31
--  37
--  41
--  43
--  47
--  53
--  59
--  61
--  67
--  71
--  73
--  79
--  83
--  89
--  97
--(25 rows)

参考文献:《SQL进阶教程》作者:[日]MICK 译者:吴炎昌 人民邮电出版社 出版时间:2017-11 / 1-8 EXISTS 谓词用法

你可能感兴趣的:(笔记,sql,数据库,database)