SQLite合并/联合/展开子查询

46scxncf  于 2023-03-13  发布在  SQLite
关注(0)|答案(1)|浏览(223)

我正尝试以与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,它只适用于一个表;我不能对表中的所有行执行相关子查询。

ssm49v7z

ssm49v7z1#

计算质数 * 是 * 一项资源密集型任务。下面是一个蛮力方法:

with recursive nums(i, max_n) as (
    select 3, max(n) max_n from target
    union all
    select i + 2, max_n from nums where i < max_n
)
select n.i
from nums n
inner join target t on n.i between t.i and t.n 
where not exists (
    select 1 
    from nums n1
    where n1.i < n.i and n.i % n1.i = 0
)

递归查询生成从3到target上限的所有奇数。然后,外部查询使用join筛选目标范围内的数字列表,并使用not exists确保我们选取的数字不是较小数字的倍数。
理想情况下,我们应该有一种方法在递归查询中构建素数列表,但这需要在from子句中重新打开递归CTE......正如您所经历的,大多数数据库引擎目前都不支持。

Demo on DB Fiddle-适用于范围25-50:

| 我|
| - ------|
| 二十九|
| 三十一|
| 三十七|
| 四十一|
| 四十三|
| 四十七|
注意:fiddle不支持generate_series,但如果您的数据库支持,那么我们可以缩短查询:

select n.i
from (select value i from generate_series(3, ( select max(n) from target ), 2 ) n
inner join target t on n.i between t.i and t.n 
where not exists (
    select 1 
    from nums n1
    where n1.i < n.i and n.i % n1.i = 0
)

相关问题