使用递归查询从表中获取电子邮件线程

时间:2019-04-24 08:48:34

标签: sql postgresql hierarchical-data recursive-query

我有一张桌子emails


     id     message_id          in_reply_to
      1     <me123@gmail.com>   null
      2     <me345@gmail.com>   <me123@gmail.com>
      3     <me567@gmail.com>   <me345@gmail.com>
      4     <me768@gmail.com>   <me567@gmail.com>
      5     <me910@gmail.com>   null
      6     <me911@gmail.com>   <me768@gmail.com>
      7     <me912@gmail.com>   <me567@gmail.com>
      8     <me913@gmail.com>   <me912@gmail.com>
      9     <me914@gmail.com>   <me913@gmail.com>
      10    <me915@gmail.com>   <me914@gmail.com>
      11    <me916@gmail.com>   <me914@gmail.com>
     ...

(此表包含电子邮件线程,我们需要获取电子邮件线程)

  1. 我只知道电子邮件的message_idid,并且其in_reply_to可以为null或不为null。
  2. 我需要获取in_reply_to等于我们知道的message_id的所有消息中的所有idmessage_id,并继续使用in_reply_to进行获取。
  3. 一旦提取了message_id,我需要搜索其他in_reply_to字段为message_id的电子邮件,并提取直到即将来临的message_id不是其他任何消息的in_reply_to
  4. foreign_key没有in_reply_to关系 就像其他任何一列一样,它只是一个列表。
  5. id是电子邮件表的主键,message_id对于每封电子邮件始终是唯一的。
  6. 一个message_id可以是许多邮件中的in_reply_to

如果我通过message_id = <me912@gmail.com>

我的输出表应该是

      id     message_id          in_reply_to      
      8     <me913@gmail.com>   <me912@gmail.com>
      9     <me914@gmail.com>   <me913@gmail.com>
      10    <me915@gmail.com>   <me914@gmail.com>
      11    <me916@gmail.com>   <me914@gmail.com>

我只知道我需要使用递归,并且对WITH RECURSIVE-https://www.postgresql.org/docs/current/queries-with.html

有所了解

我做了一些尝试:

    WITH RECURSIVE emails AS (
    SELECT message_id, in_reply_to FROM emails WHERE id = ?
    UNION ALL
    SELECT message_id, in_reply_to
     FROM emails where in_reply_to =  // Stuck here
   )
   SELECT * 
   FROM emails;

可以帮我解决该查询吗?

1 个答案:

答案 0 :(得分:1)

加入CTE比较email_idin_reply_to

WITH RECURSIVE
thread
AS
(
SELECT e.id,
       e.message_id,
       e.in_reply_to
       FROM emails e
       WHERE id = 8
UNION ALL
SELECT e.id,
       e.message_id,
       e.in_reply_to
       FROM emails e
            INNER JOIN thread t
                       ON t.message_id = e.in_reply_to
)
SELECT *
       FROM thread
       ORDER BY id;

db<>fiddle