PostgreSQL - упорядочивание перемешанных данных (рекурсивно?) - PullRequest
0 голосов
/ 22 ноября 2018

У меня есть неупорядоченные данные в базе данных PostgreSQL, которые выглядят следующим образом:

ID  PATH    START   END
7   A123    B       C
4   B456    D       E
9   A123    A       B
2   B456    A       B
6   B456    B       C
21  A123    C       D
3   B456    C       D
5   B456    E       F

Значения START и END нельзя упорядочить в алфавитном порядке, они просто используются для иллюстрации проблемы

Я пытаюсь добиться этого:

id  path    sequence    start   end
9   A123    1           A       B
7   A123    2           B       C
21  A123    3           C       D
2   B456    1           A       B
6   B456    2           B       C
3   B456    3           C       D
4   B456    4           D       E
5   B456    5           E       F

Логика, о которой я думаю, чтобы достичь этого, чтобы определить начальное значение (представленное как A) для каждого пути (A123 / B456).Затем определяют последовательность AB, BC, CD и т. Д.).Который нужно повторить для всех путей.

Я написал рекурсивный запрос, который выполняет итерацию по заданному имени пути (см. WHERE path = 'B456')

WITH RECURSIVE ordered(id, path, sequence, "start", "end") AS (
WITH path AS (SELECT id, "path", "start", "end"
FROM unordered
WHERE path = 'B456'),
startofpath AS (SELECT p1.id
FROM unordered p1
LEFT JOIN unordered p2 ON p1.start = p2.end
WHERE p2.start IS NULL)

--find start of path (A)
SELECT path.id, path.path, 1, path.start, path.end
FROM path, startofpath
WHERE path.id = startofpath.id
UNION ALL
--add on next path (B -> C)
SELECT path.id, path.path, ordered.sequence + 1, path.start, path.end FROM 
path
INNER JOIN ordered
ON path.start = ordered."end")
SELECT * FROM ordered

Образец данных:

CREATE table unordered (
id   INT PRIMARY KEY,
path TEXT NOT NULL,
"start" TEXT NOT NULL,
"end" TEXT NOT NULL);

INSERT INTO unordered (id, path, "start", "end") VALUES (7,'A123','B','C');
INSERT INTO unordered (id, path, "start", "end") VALUES (4,'B456','D','E');
INSERT INTO unordered (id, path, "start", "end") VALUES (9,'A123','A','B');
INSERT INTO unordered (id, path, "start", "end") VALUES (2,'B456','A','B');
INSERT INTO unordered (id, path, "start", "end") VALUES (6,'B456','B','C');
INSERT INTO unordered (id, path, "start", "end") VALUES (21,'A123','C','D');
INSERT INTO unordered (id, path, "start", "end") VALUES (3,'B456','C','D');
INSERT INTO unordered (id, path, "start", "end") VALUES (5,'B456','E','F');

В чем проблема, с которой я сталкиваюсь, это как пройти по всем путям (A123, затем B456 и т. Д.)

Может ли кто-нибудь помочь с этим следующим шагом?(или переработать мой запрос с нуля, если у меня совершенно неверная идея)

Большое спасибо!

1 Ответ

0 голосов
/ 22 ноября 2018

Это то, что вы ищете?

WITH RECURSIVE
get_path(id, path, sequence, starting, ending) AS (
    SELECT u.id, u.path, 1, u.starting, u.ending 
    FROM unordered AS u
    WHERE u.starting NOT IN (SELECT u.ending FROM unordered AS u) -- a starting point has no entry in ending column

    UNION

    SELECT u.id, u.path, g.sequence + 1, g.ending, u.ending
    FROM get_path AS g, unordered AS u
    WHERE u.starting = g.ending
)
TABLE get_path ORDER BY path, sequence;

Обратите внимание, что я изменил "start" на starting и "end" на ending.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...