Нужна помощь в поиске cycle-s из массива или строк на основе шаблона - PullRequest
0 голосов
/ 13 апреля 2019

У меня есть набор данных, который содержит определенные последовательности, которые уже были найдены.

Последовательность может быть в виде массива:

    {1288,122,1288,127}
    {286,286,260,260}

Или просто строки с пользователем, id, site_id

    A | 252 | 1288
    A | 253 | 122
    A | 254 | 1288
    A | 255 | 127

Я пытаюсь найти на основе шаблона site_id-s, если массив или строки имеют круглую форму.

Итак, первый пример A-B-A-C. Второй не так, как сайты А-А-В-В. Хитрость в том, что между последовательностями может быть более одного сайта, и мне еще предстоит найти решение даже для простого A-B-A

Я пытался найти какой-то материал, но все относится к сопоставлению строковых шаблонов или ко всем другим типам поиска циклов в массиве, которые не соответствуют моей проблеме.

Я ожидаю, что в основном получу значение true или false, если в этой последовательности есть цикл или нет. Получение идентификатора сайта, который является цикличным, было бы бонусом.

1 Ответ

0 голосов
/ 13 апреля 2019

Вы можете unnest() массив WITH ORDINALITY и проверить, существуют ли в множестве две строки с одинаковым значением, но с порядковым числом по крайней мере в двух.

WITH 
cte
AS
(
SELECT *
       FROM unnest('{1288,122,1288,127}'::integer[]) WITH ORDINALITY un(v, o)
)
SELECT EXISTS (SELECT *
                      FROM cte c1
                      WHERE EXISTS (SELECT *
                                           FROM cte c2
                                           WHERE c2.v = c1.v
                                                 AND c2.o > c1.o + 1));

Для задачи на основе множества вы 'Мне нужен столбец для заказа.Но тогда это по сути то же самое.Если этот столбец для сортировки не позволяет напрямую реализовать логику, например, потому что это строка, в которой + 1 не будет работать хорошо, вы можете использовать row_number() для получения подходящих порядковых чисел.

Чтобы получить числа, которые являются «терминалами» в цикле (может быть больше одного), просто удалите внешний EXISTS и спроецируйте значение.

WITH 
cte
AS
(
SELECT *
       FROM unnest('{1288,122,1288,127}'::integer[]) WITH ORDINALITY un(v, o)
)
SELECT v
       FROM cte c1
       WHERE EXISTS (SELECT *
                            FROM cte c2
                            WHERE c2.v = c1.v
                                  AND c2.o > c1.o + 1);

db <> fiddle

...