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 谓词用法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不停感叹的老林_<C 语言编程核心突破>

不打赏的人, 看完也学不会.

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值