我正尝试以与https://www.sqlite.org/lang_with.html中的“古怪递归查询”示例相同的方式编写一些SQL代码。
特别是,我尝试用SQL创建一个主筛,我尝试用EXCEPT
代替union进行递归cte,但这是禁止的:
CREATE TABLE target AS SELECT 25 AS i, 100 AS n;
WITH RECURSIVE primes AS (
SELECT
value AS p
FROM GENERATE_SERIES(3, (SELECT target.n FROM target LIMIT 1), 2)
EXCEPT
SELECT
(SELECT value FROM GENERATE_SERIES(p*p, (SELECT target.n FROM target LIMIT 1), p))
FROM
primes
)
这会失败,因为递归ctes中不允许EXCEPT
子句,只允许UNION
,也可能是INTERSECT
。
不管怎样,我尝试了效率较低但不那么荒谬的方法
WITH multiples AS (
SELECT
(SELECT value AS p FROM GENERATE_SERIES(n.value*n.value, (SELECT target.n FROM target LIMIT 1), n.value))
FROM
GENERATE_SERIES(3, (SELECT SQRT(target.n) FROM target LIMIT 1), 2) n
)
SELECT * FROM multiples;
但结果只是9, 25, 49, 81
,而不是9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 87, 93, 99, 25, 35, 45, 55, 65, 75, 85, 95, 49, 63, 77, 91, 81, 99
如何合并子查询结果,而不是只取每个结果的第一个条目?
我认为有一个名为UNNEST
的函数在某些SQL风格中可以神奇地做到这一点,但它不在SQLite中。我读到SQLite实际上并没有实现数组,这就解释了为什么GENERATE_SERIES
只能用作表,而UNNEST
是缺失的,但我对SQL了解不多,所以我不知道这一切的含义。UNION ALL
也能很好地工作,除了afaik,它只适用于一个表;我不能对表中的所有行执行相关子查询。
1条答案
按热度按时间ssm49v7z1#
计算质数 * 是 * 一项资源密集型任务。下面是一个蛮力方法:
递归查询生成从3到
target
上限的所有奇数。然后,外部查询使用join
筛选目标范围内的数字列表,并使用not exists
确保我们选取的数字不是较小数字的倍数。理想情况下,我们应该有一种方法在递归查询中构建素数列表,但这需要在
from
子句中重新打开递归CTE......正如您所经历的,大多数数据库引擎目前都不支持。Demo on DB Fiddle-适用于范围25-50:
| 我|
| - ------|
| 二十九|
| 三十一|
| 三十七|
| 四十一|
| 四十三|
| 四十七|
注意:fiddle不支持
generate_series
,但如果您的数据库支持,那么我们可以缩短查询: