Решение
Най-вероятно решението е да се квалифицира по схема на оператора:
SELECT *
FROM test
WHERE tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER BY id
LIMIT 100;
Защо?
Това е проблем соператорската резолюция (в комбинация с разделителна способност на типа и контекст на предаване).
В стандартния Postgres има само един оператор кандидат anyarray @> anyarray
, това е този, който искате.
Вашата настройка би работила добре, ако не сте инсталирали допълнителния модулен intarray (моето предположение), което предоставя друг оператор за integer[] @> integer[]
.
Следователно, друго решение би било да се използва integer[]
вместо това и да има GIN индекс с gin__int_ops
оператор клас. Или опитайте (по подразбиране за intarray) gist__int_ops
индекс. И двете може да са по-бързи, но и двете не позволяват NULL стойности.
Или можете да преименувате intarray
оператор @>
да се уточнява. (Не бих направил това. Възникват проблеми с надстройката и преносимостта.)
За изрази, включващи поне един операнд от тип integer[]
, Postgres знае кой оператор да избере:операторът intarray. Но тогава индексът не е приложим , тъй като операторът intarray работи само с integer
(int4
) не int2
. И индексите са строго обвързани с операторите:
- Може ли PostgreSQL да индексира колони от масиви?
- Поведение на PostgreSQL при наличие на два различни типа индекси в една и съща колона
Но за int2[] @> int2[]
, Postgres не може да определи най-добрия оператор. И двете изглеждат еднакво приложими. Тъй като операторът по подразбиране е предоставен в pg_catalog
схемата и операторът intarray се предоставя в public
схема (по подразбиране - или където и да сте инсталирали разширението), можете да помогнете за разрешаването на загадката, като квалифицирате оператора по схема с OPERATOR()
конструкция. Свързано:
- Сравнете масивите за равенство, като игнорирате реда на елементите
Съобщението за грешка, което получавате, е малко подвеждащо. Но ако погледнете внимателно, има HINT
добавен ред, който намеква (така!) в правилната посока:
ERROR: operator is not unique: smallint[] @> smallint[] LINE 1: SELECT NULL::int2[] @> NULL::int2[] ^ HINT: Could not choose a best candidate operator. You might need to add explicit type casts.
Можете да проучите съществуващи кандидати за оператор за @>
с:
SELECT o.oid, *, oprleft::regtype, oprright::regtype, n.nspname
FROM pg_operator o
JOIN pg_namespace n ON n.oid = o.oprnamespace
WHERE oprname = '@>';
Друго алтернативно решение би било временно(!) да зададете различен search_path, така че да се намери само желания оператор. В същата транзакция:
SET LOCAL search_path = pg_catalog;
SELECT ...
Но тогава трябва да квалифицирате схематично всички таблици в заявката.
Относно контекста на предаване:
- Генерирайте поредица от дати – като използвате тип дата като вход
Вие можете променете castcontext
на int2
-> int4
. Но аз силно не го съветвам. Твърде много възможни странични ефекти:
- Има ли някакъв начин за прехвърляне на тип данни на postgresql 9.3, така че да може да засегне само едната страна