有人可以向我解释这个SQL查询是如何工作的吗?
WITH recursive n(n) AS (
SELECT 2 n
UNION ALL
SELECT n+1 FROM n WHERE n<1000
)
SELECT a.n
FROM n a
LEFT JOIN n b
ON b.n < sqrt(a.n)
GROUP BY a.n
HAVING a.n=2 OR MIN(a.n % b.n) > 0;
这将在PostgresQL中生成以下内容:
n
====
251
887
601
647
577
...
9
(177 rows)
我对逐行细分的理解:
SELECT 2 n
- 选择数字2作为n [CTE的锚点成员]
UNION ALL
- 与n&lt; 1000中的递归分量n + 1结合使用,因此显示2到1000之间的所有数字
SELECT a.n FROM n a
- 运行上述查询[CTE的递归成员]
LEFT JOIN n b
- 左边用数字2-1000连接第二组数字
ON b.n < sqrt(a.n)
- 第二组数字是否小于第一列数字的平方根?
GROUP BY a.n
- 仅显示第一列数字
HAVING a.n=2 OR MIN(a.n. % b.n) > 0
- ...其中A = 2或A模B的最小值是否大于0?
这是一个愚蠢的查询,但任何解密的帮助都将不胜感激。
答案 0 :(得分:4)
您的查询经过适当修复后,会生成1000以下的素数列表:
WITH recursive n(n) AS (
SELECT 2 n
UNION ALL
SELECT n+1 FROM n WHERE n<1000
)
SELECT a.n
FROM n a
LEFT JOIN n b
ON b.n <= sqrt(a.n) -- Fix #1
GROUP BY a.n
HAVING a.n=2 OR a.n=3 OR MIN(a.n % b.n) > 0 -- Fix #2
ORDER BY a.n ASC
解释相当简单:查询的递归部分只是一种方法,可以为您提供从2(包括)到1000(不包括)的数字列表。您可以使用填充了连续整数的实际表替换recursive子句。
然后将这些数字输入查询的非CTE部分,并在b.n < sqrt(a.n)
条件下加入自己。 a
侧代表候选素数; b
方代表候选除数。
以下是查询中的第一个错误:<
必须更改为<=
,否则素数正方形的平方根将包含在输出中。
GROUP BY
将潜在素数与其候选除数组合成一个组。 HAVING
子句会删除所有具有一个或多个候选除数的所有除数,均衡地划分候选素数,即MIN(a.n % b.n)
为零。
这是您需要第二次修复的地方,因为素数3
的平方根小于2
,即列表中最小的候选除数。因此,3
最终根本没有候选除数,并被HAVING
子句抛出;您需要添加OR a.n=3
才能保留它。