PostgreSQL递归选择从叶子中查找根元素

2024-02-06

我正在为论坛开发一个数据库,其中包含线程和消息。线程以一条没有消息的消息开始parent_id;回复是消息parent_id.

我有一张消息表。每个项目都引用同一个表上的项目,将它们作为父子关系。

create table messages(
  id int,
  title text,
  content text,
  parent_id int
);

现在我用一些数据填充表格:

insert into messages values 
(1, 'One', 'First  thread main post', null), -- First thread
(2, 'Two', 'First thread reply', 1), 
(3, 'Three', 'First thread reply', 2),
(4, 'Four', 'Second thread main post', null), -- Second thread
(5, 'Five', 'Second thread reply', 4),
(6, 'Six', 'Second thread reply', 5),
(7, 'Six', 'Second thread reply', 6),
(8, 'Six', 'Second thread reply', 7),
(9, 'Six', 'Second thread reply', 8); 

知道id对于线程的第一条消息,我可以使用递归查询检索所有回复:

with recursive my_tree as (
    select * from messages 
    where parent_id IS null and id = 4
  union all
    select messages.* from messages 
    join my_tree on messages.parent_id = my_tree.id
) select my_tree.* 
    from my_tree;

这里有一个.

现在,假设我知道id一些答复,我想得到id线程的第一条消息。我该怎么做?

编辑: 我知道我可以从已知的线程中检索所有消息id向上:

with recursive my_tree as (
    select * from messages 
    where id = 9
  union all
    select messages.* from messages 
    join my_tree on messages.id = my_tree.parent_id
) select my_tree.* 
    from my_tree;

Here a 但如果线程由数千条消息组成,效率就会降低。有没有什么方法可以让递归查询到达第一项而不检索所有消息?


以目前的数据结构,除了访问从叶子到根的整个路径之外,没有其他办法。您可以通过仅对关键列进行操作来加快搜索速度:

with recursive my_tree as (
    select id, parent_id
    from messages 
    where id = 9
union all
    select m.id, m.parent_id 
    from messages m
    join my_tree t on m.id = t.parent_id
) 
select m.*
from messages m
join my_tree t using(id)
where t.parent_id is null

如果这个解决方案不令人满意,可以考虑在表中添加一列

alter table messages add root_id int;

使用递归查询填充此列将很容易,并且您将可以立即访问每个节点的根。

另一种方法是使用以下方法更改数据结构l树扩展。 https://www.postgresql.org/docs/current/ltree.html

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

PostgreSQL递归选择从叶子中查找根元素 的相关文章

随机推荐

  • 文件内容更改后使用 ifstream 从同一文件读取(直到 EOF)

    要求 我必须读到 EOF 16 个字节 时间 来自特定文件 以及 然后说睡5秒 现在 5秒后 当我尝试阅读时 从文件 其内容将 到那时已被附加 预期的设计必须是这样的 它从它所在的点读取 之前离开并再次扫描 内容 一次 16 个字节 直到
  • bigint 通过 PDO 截断?

    我遇到了将大整数存储在 a 中的问题BIGINT通过 PDO 在 MySQL 上列 如果我运行这个测试 number 30123456789 var dump number prints string 11 30123456789 new
  • 使用 Connect-MSOLservice 与服务主体连接

    我正在尝试使用在 AzureAD 中创建的服务主体通过 PowerShell 脚本进行连接 我成功创建了 SP 创建了密钥 还创建了自签名证书并将其与帐户关联 我知道如何使用 Connect AzureAD 但 Connect MSOLse
  • 可以使用按钮删除从项目添加的数据库条目吗?

    我正在尝试使用 Android 编程 大书呆子牧场指南 自学 Android 开发 其中一个练习 如果您熟悉这本书 请从第 14 章开始 涉及创建一个工具栏 其中包含一个项目 该项目将新条目添加到单击该项目时的数据库 一个挑战问题是删除条目
  • 使用 JGit 从 Git 检索提交消息日志

    我只想从 Git 存储库检索提交日志 其中包含您在特定存储库上完成的所有提交的消息 我找到了一些实现此目的的代码片段 并以异常结束 try FileRepositoryBuilder builder new FileRepositoryBu
  • Kivy 窗口隐藏/显示

    我是一个Python编程新手 学习让我创建一个项目 这就是我正在尝试做的事情 我想创建一个在系统托盘中运行的程序 并且 fire 是一个在后台加载的程序 在后台加载 这样我可以减少 Kivy 的启动时间 在这里和谷歌搜索后 我找不到答案 我
  • Azure ARM 角色分配不同的资源组

    我正在尝试创建一个具有 VM 的 ARM 模板 我希望 VM 具有AcrPull向位于不同资源组中的容器注册表进行角色分配 我将范围属性设置为 ACR 的 ID 我从https resources azure com https resou
  • 正则表达式 标签解析src、宽度、高度

    你可能会对这句话做出反应 H使用正则表达式进行 TML 解析是一个完全糟糕的主意 下列的this https stackoverflow com questions 1732348 regex match open tags except
  • 添加对消息的反应。 Discord.py 重写

    我正在尝试使用自定义表情符号添加对消息的反应 由于某种原因 我在网上找不到太多与此相关的内容 并且我花了过去 3000 万的时间试图找出不同的方法 到目前为止还没有任何效果 这是在齿轮内部 第一种方法 accept decline awai
  • Xcode + 删除所有断点

    有什么方法可以删除Xcode中的所有断点吗 那么有一个三步的方法 按 CMD 7 显示所有断点 在 Xcode4 中按 CMD 6 在 Xcode3 中按 CMD ALT B 使用 CMD A 选择所有断点 然后使用退格键删除它们 就像删除
  • 乔姆斯基语言类型

    我试图理解四种不同的乔姆斯基语言类型 但我发现的定义对我来说没有任何意义 我知道类型 0 是自由语法 类型 1 是上下文相关的 类型 2 是上下文无关的 而类型 3 是常规的 那么 有人可以解释一下这一点并将其放在上下文中吗 谢谢 语言是属
  • 有没有办法在没有 .* 或 ->* 运算符的情况下调用成员函数

    调用方法如下D foo通过指向成员函数的指针调用函数将生成错误 必须使用 or gt 在 f 中调用指向成员函数的指针 当然这不是我们调用成员函数指针的方式 正确的调用方式是 d f 5 OR p gt f 5 我的问题是 有没有办法在左侧
  • 如何使用 scipy.optimize.linprog 获得整数解?

    当我解决线性规划问题时 就像下面的公式一样 我希望 x 的结果全部为 int 类型 考虑以下问题 最小化 f 1 x 0 4 x 1 须遵守 3 x 0 1 x 1 lt 6 1 x 0 2 x 1 lt 4 x 1 gt 3 where
  • [mccabe] 循环复杂度过高错误是什么意思?

    我正在 repl it 中为一个学校项目创建一个 CYOA 并且需要一个列表 所以我所做的就是在每次输入时为用户添加一个选项来查看他们的项目 在主要的分割处我放了 Items Flask of Root Beer print Intro n
  • python:使用 gdal 绑定在内存中执行 gdalwarp

    我目前有一个加工链R下载MODIS数据然后调用gdalwarp从系统将特定子数据集 例如 NDVI 重新投影到 WGS1984 中 所结果的GeoTiffs然后被收集到一个HDF5文件以供进一步处理 现在我将处理链移至python 我想知道
  • 计算 BigQuery 中分区的运行总和

    我正在尝试计算分区上的运行总和 这似乎比中建议的方法更容易和更快BigQuery SQL 运行总计 https stackoverflow com questions 14664578 bigquery sql running totals
  • 使用 R 转换为 NetCDF 时保留栅格变量名称

    获取多年每月温度数据的光栅文件 该文件附有名称 可通过以下方式访问names object 采用以下格式 Jan 1981 Feb 1981 等 使用以下代码的两年示例文件here http www filedropper com samp
  • 如何使用 Windows 内置的 mp3 解码器访问原始解码音频数据?

    从 Windows Media Player 6 1 开始 Windows 就有了自己的 mp3 解码器 我可以使用该解码器来访问解码的音频 原始 数据吗 我认为这必须通过 DirectShow 来完成 Related but not th
  • 从 Git Bash 调用 notepad++

    我在用msysgit http msysgit github com 在 Windows 7 中 如何从 Git Bash 调用 notepad 就像我们使用默认记事本一样 比如说 name usename记事本文本文件 txt 相反 我希
  • PostgreSQL递归选择从叶子中查找根元素

    我正在为论坛开发一个数据库 其中包含线程和消息 线程以一条没有消息的消息开始parent id 回复是消息parent id 我有一张消息表 每个项目都引用同一个表上的项目 将它们作为父子关系 create table messages i