这个递归 SQL CTE 究竟是如何工作的?

2024-04-13

有人可以向我解释一下这个 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

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?

这是一个愚蠢的查询,但任何破译它的帮助将不胜感激。


如果正确修复您的查询,则会生成 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

Demo. http://sqlfiddle.com/#!15/9eecb7db59d16c80417c72d1e1f4fbf1/7239

解释相当简单:查询的递归部分只是为您提供从 2(含)到 1000(不含)的数字列表的一种方法。您可以将递归子句替换为填充连续整数的实际表。

然后,这些数字将被输入查询的非 C​​TE 部分,并根据条件连接到自身b.n < sqrt(a.n). The aside 代表候选素数;这bside 代表候选除数。

这是查询中的第一个错误:<必须改为<=,否则素数平方的平方根将包含在输出中。

The GROUP BY将潜在素数及其候选约数分组为一组。HAVING子句会丢弃所有带有一个或多个候选除数的所有内容,将候选质数均匀地除,即MIN(a.n % b.n)为零。

这是您需要第二次修复的地方,因为3,质数,小于2,列表中最小的候选除数。因此,3最终根本没有候选除数,并被抛出HAVING条款;你需要添加OR a.n=3来保存它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

这个递归 SQL CTE 究竟是如何工作的? 的相关文章

  • 触发器以捕获服务器中的架构更改

    是否可以实现类似以下触发器的东西 CREATE TRIGGER tr AU ddl All Server ON DATABASE WITH EXECUTE AS self FOR DDL DATABASE LEVEL EVENTS AS D
  • oracle中是否有相当于concat_ws的东西?

    我有大量的列试图聚合在一起 其中大多数都有 NULL 值 我想分隔确实以 出现的值但我在oracle中找不到有效的方法来做到这一点 CONCAT WS 正是我所需要的 因为它不会在 NULL 值之间添加分隔符 但 Oracle 不支持这一点
  • Google BigQuery:如何使用 SQL 创建新列

    我想在不使用旧版 SQL 的情况下向现有表添加一列 基本的 SQL 语法是 ALTER TABLE table name ADD column name datatype 我格式化了 Google BigQuery 的查询 ALTER TA
  • 选择表中的人员并排除妻子,但合并他们的名字

    我有一张桌子Person PersonID FirstName LastName 1 John Doe 2 Jane Doe 3 NoSpouse Morales 4 Jonathan Brand 5 Shiela Wife And a R
  • SQL Server 2005 - 达到表行大小限制

    有没有一种干净的方法可以在向表添加新列之前确定表的行大小 并且不超过 8060 字节的限制 例如 如果表行长度当前为 8055 字节 并且我想添加日期时间 8 字节 则这将结束 因为它将变为 8063 字节 不包括空映射 但是 如果我添加一
  • Spring Boot如何加入自定义查询

    我需要创建一个端点 该端点按州返回人口普查数据以及城市列表 我目前使用两个端点来获取此数据 目前回应 自定义查询一 censusByState id 1 code 11 name Rond nia statePopulation 18152
  • Sql 查询抛出标识符太长。最大长度为 128

    我正在处理一个简单的更新查询 在执行查询时看到以下错误 我非常清楚 这根本不应该是一个长度问题 可能是什么问题 Error 以identifier开头的标识符太长 最大长度为 128 我的查询 update dbo DataSettings
  • SQL Server - 在设置 COLLATE Latin1_General_CS_AS 的情况下搜索不区分大小写

    家长提问 https stackoverflow com questions 50974562 sql server update to match and replace only exact words感谢 Iamdave 部分问题得到
  • 小数除以小数并得到零

    为什么当我这样做时 select CAST 1 AS DECIMAL 38 28 CAST 1625625 AS DECIMAL 38 28 我得到 0 吗 但是当我得到 0 时 select CAST 1 AS DECIMAL 20 10
  • 如何将数据插入 Microsoft Access 数据库?

    我正在尝试将数据插入 Microsoft Access 数据库 我将数据插入到 Access 数据库中 但只有第一次和第二次显示我插入的数据 当我重建应用程序时 我插入的数据消失了 我不知道他们去了哪里并且没有出现 我使用 C 和 NET
  • 不使用窗口函数实现 SQL 查询

    我读过 可以通过创造性地使用连接等来实现在 SQL 窗口函数中可以执行的任何操作 但我不知道如何实现 我在这个项目中使用 SQLite 它目前没有窗口函数 我有一个有四列的表 CREATE TABLE foo id INTEGER PRIM
  • 在触发器中记录更新操作

    我有一个 UPDATE 触发器 它生成 INSERTED 和 DELETED 表 如下所示 INSERTED Id Name Surname 1 Stack Overflow 2 Luigi Saggese DELETED Id Name
  • 如何在一列中存储数组或多个值

    运行 Postgres 7 4 是的 我们正在升级 我需要将 1 到 100 个选定项目存储到数据库的一个字段中 98 的情况下 只会输入 1 个项目 而 2 的情况下 如果是这样的话 会输入多个项目 这些项目只不过是文本描述 截至目前 长
  • sql查询连接两个服务器中不同数据库的两个表

    我在 ServerS 上的数据库中有两个表 tableA 在 ServerB 上的数据库中有两个表 我只想根据这些表的公共字段名对这些表执行 fullouter join 在 SQL Server 中 您可以创建一个链接服务器 在 Mana
  • 将数组文字传递给 PostgreSQL 函数

    我有一个包含 select 语句的 Postgres 函数 我需要使用包含字符串值数组的传入变量添加条件 CREATE OR REPLACE FUNCTION get questions vcode text RETURN return v
  • BULK INSERT 中格式附近的语法不正确?

    我试图找出为什么我使用的 BULK INSERT 命令无法识别命令中使用的 FORMAT 和 FIELDQUOTE 选项 BULK INSERT dbo tblM2016 RAW Current Import File FROM x tms
  • 在 Oracle 中创建数据库链接时出错

    我有两个数据库 需要编写跨数据库查询 所以我试图创建一个数据库链接 CREATE PUBLIC DATABASE LINK DBLink CONNECT TO SchemaName IDENTIFIED BY 123 using DBNam
  • 如何将 T-SQL 中的结果连接到列中?

    我正在处理一个查询 它应该给我这样的结果 Name Surname Language Date James Hetfield en gb fr 2011 01 01 Lars Ulrich gb fr ca 2011 01 01 但我的选择
  • MySQL:用户对数据库的访问被拒绝

    我正在尝试在 Heroku 上的远程 SQL 服务器上创建一个数据库 clearDB 我与此联系 mysql host lt
  • 从Oracle表中删除重复行

    我正在 Oracle 中测试某些内容并使用一些示例数据填充表 但在此过程中我不小心加载了重复记录 因此现在我无法使用某些列创建主键 如何删除所有重复行并只保留其中一行 Use the rowid伪列 DELETE FROM your tab

随机推荐