DISTINCT ON
, как и в случае с Гордоном, вполне допустимо и просто. Основы:
Вы можете использовать конструкцию с unnest()
и WITH ORDINALITY
и предоставляет массив только с кодами, отсортированными по вашему предпочтению:
SELECT DISTINCT ON (SponsorID) t.*
FROM unnest('{7101, 7102, 1010}'::int[]) WITH ORDINALITY x(code, ord)
JOIN tbl t USING (code)
ORDER BY t.SponsorID, x.ord;
См .:
Простой индекс помогает производительности , если коды интересов не слишком распространены:
CREATE INDEX ON tbl (code);
Но Ваши выборочные значения предполагают, что много строк на (SponsorID, code)
. Итак, 2 вещи:
1. Корректность
Определите, какую строку выбрать при наличии нескольких, с помощью code = 7101
et c. Что-то вроде "самый маленький id
первый" . Вы можете просто добавить к запросу еще одно ORDER BY
выражение:
...
ORDER BY t.SponsorID, x.ord, <b>t.id</b>;
Но рассмотрим ...
2. Производительность
Предполагая, что существует таблица sponsor
с 1 строкой на спонсора (что обычно у вас есть), рассмотрим этот более сложный запрос:
SELECT t.*
FROM sponsor s
CROSS JOIN LATERAL (
(SELECT * FROM tbl t WHERE t.SponsorID = s.id AND code = 7101 ORDER BY id LIMIT 1) -- ORDER BY id???
UNION ALL (SELECT * FROM tbl t WHERE t.SponsorID = s.id AND code = 7102 ORDER BY id LIMIT 1)
UNION ALL (SELECT * FROM tbl t WHERE t.SponsorID = s.id AND code = 1010 ORDER BY id LIMIT 1)
LIMIT 1
) t
;
db <> fiddle здесь
В сотрудничестве с этим индексом:
CREATE INDEX ON tbl (SponsorID, code, id);
Теперь мы получаем быстрое сканирование индекса, только чтение строк, которые нам действительно нужны.
Если вас не волнует «сначала самое маленькое id
», обрежьте его из запроса и индекса.
Есть даже способы без таблицы sponsor
, но мы слишком углубляемся ... См .: