Рекурсивная версия
@ Демс побеждает меня к этому: рекурсивный CTE - это путь к здесь. Работает для любой последовательности чисел. Я публикую свою версию, потому что:
- Не требует дополнительной таблицы. Просто вставьте свои порядковые номера в виде массива.
- Сам рекурсивный CTE проще.
- Последний запрос умнее.
- На самом деле это работает в PostgreSQL. Рекурсивная версия @Dems не является синтаксически правильной в своем текущем состоянии.
Тестовая настройка:
CREATE TEMP TABLE t (id int, val int);
INSERT INTO t VALUES
(1,4),(2,5),(3,1)
,(4,5),(5,6),(6,1)
,(7,3),(8,2),(9,7);
Звоните:
WITH RECURSIVE x AS (
SELECT '{1,5,6,1,3}'::int[] AS a
), y AS (
SELECT t.id AS start_id
,1::int AS step
FROM x
JOIN t ON t.val = x.a[1]
UNION ALL
SELECT y.start_id
,y.step + 1 -- AS step -- next step
FROM y
JOIN t ON t.id = y.start_id + step -- next id
JOIN x ON t.val = x.a[1 + step] -- next value
)
SELECT y.start_id
FROM x
JOIN y ON y.step = array_length(x.a, 1) -- only where last steps was matched
Результат:
3
Статическая версия
Работает для предварительно определенного числа элементов массива, но быстрее для небольших массивов. 5 пунктов в этом случае. Те же настройки теста, что и выше.
WITH x AS (
SELECT '{1,5,6,1,3}'::int[] AS a
)
SELECT t1.id
FROM x, t t1
JOIN t t2 ON t2.id = t1.id + 1
JOIN t t3 ON t3.id = t1.id + 2
JOIN t t4 ON t4.id = t1.id + 3
JOIN t t5 ON t5.id = t1.id + 4
WHERE t1.val = x.a[1]
AND t2.val = x.a[2]
AND t3.val = x.a[3]
AND t4.val = x.a[4]
AND t5.val = x.a[5];