


Клиент передал ID товаров [30, 10, 30, 99]. Нужно получить именно четыре позиции: повтор 30 сохранить, а для неизвестного 99 показать отсутствие товара. В разборе Mentoring.digital развернём массив в строки, добавим номер позиции и соединим результат с каталогом.
Условие WHERE id = ANY(...) отвечает на вопрос о принадлежности набору. Оно не превращает повторяющийся ID в две строки каталога и не закрепляет порядок выдачи. Поэтому для этой задачи входной список должен стать самостоятельной таблицей с позицией каждого элемента.
unnest() разворачивает массив, а WITH ORDINALITY добавляет к результату порядковый номер типа bigint начиная с 1. Названия id и pos ниже задаются явно через псевдоним.
WITH catalog(id, title) AS (
VALUES (10, 'Notebook'), (30, 'Pen')
)
SELECT requested.pos, requested.id, catalog.title
FROM unnest(ARRAY[30, 10, 30, 99])
WITH ORDINALITY AS requested(id, pos)
LEFT JOIN catalog ON catalog.id = requested.id
ORDER BY requested.pos;Ожидаемые строки: 1, 30, Pen; 2, 10, Notebook; 3, 30, Pen; 4, 99, NULL. Здесь все данные определены внутри запроса, существующие таблицы не изменяются.
LEFT JOIN сохраняет входную позицию даже без совпадения. INNER JOIN удалил бы строку 99. Повтор 30 остаётся дважды, потому что во входной таблице ему соответствуют две разные позиции. Окончательный порядок закрепляет именно ORDER BY requested.pos: наличие номера само по себе не сортирует результат.
SELECT value, pos
FROM unnest(ARRAY[]::integer[])
WITH ORDINALITY AS input(value, pos)
ORDER BY pos;
SELECT value, pos
FROM unnest(ARRAY[NULL, 10]::integer[])
WITH ORDINALITY AS input(value, pos)
ORDER BY pos;Первый запрос вернёт ноль строк. Второй сохраняет NULL как первый элемент с позицией 1, затем значение 10 с позицией 2. Порядковый номер означает положение в развёрнутом результате, а не исходную нижнюю границу индекса массива.
В реальном каталоге ID должен однозначно определять товар. Если соединяемая таблица содержит несколько строк с одним ID, каждая входная позиция может размножиться. Не маскируйте это случайным DISTINCT: сначала проверьте ключ и смысл соединения.
Передавайте массив параметром запроса, сохраняя нужный тип, вместо сборки SQL из текста пользователя. Зафиксируйте договорённость: нужны ли повторы, что делать с неизвестным ID и допустим ли NULL во входе. Изменение одного из этих решений меняет ожидаемый результат.
Запросы с массивами и соединениями можно разбирать на практическом курсе SQL. При проверке своей схемы ментору по SQL пригодятся ключи таблиц, небольшой набор входных ID и ожидаемый порядок строк.