#sql #postgresql #hierarchical-data #recursive-query
#sql #postgresql #иерархический-данные #рекурсивный запрос
Вопрос:
У меня есть таблица 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>
...
(эта таблица содержит поток электронных писем, нам нужно извлечь поток электронной почты)
- Я просто знаю
message_id
иid
электронного письма, и оноin_reply_to
может быть нулевым или не нулевым. - Мне нужно извлечь все
message_id
s иid
те сообщения, где in_reply_to равноmessage_id
известному нам, и продолжать выборку с помощью in_reply_to. - После получения message_id мне нужно искать другие электронные письма, у которых есть
in_reply_to
поле, подобное этомуmessage_id
, и извлекать до тех пор, пока в следующем message_id не будетin_reply_to
никаких других сообщений. - Нет
foreign_key
связи по отношению кin_reply_to
, и это просто список, подобный любому другому столбцу. id
является первичным ключом для таблицы электронных писем,message_id
всегда уникальным для каждого электронного письма.- Одно
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:
Присоединитесь к CTE, сравнивающему email_id
и in_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;
Комментарии:
1. Спасибо за ответ. Объяснение было бы полезным. Но это нормально: thumbsup