Има два варианта на IN
изрази:
expression IN (subquery)
expression IN (value [, ...])
По същия начин, два варианта с ANY
конструкция:
expression operator ANY (subquery)
expression operator ANY (array expression)
Подзаявката работи и за двете техники, но за втората форма на всеки, IN
очаква списък със стойности (както е дефинирано в стандартния SQL), докато = ANY
очаква масив .
Кое да използвам?
ANY
е по-късно, по-гъвкаво допълнение, може да се комбинира с всеки двоичен оператор, връщащ булева стойност. IN
изгаря до специален случай на ANY
. Всъщност втората му форма е пренаписана вътрешно:
IN
се пренаписва с = ANY
NOT IN
се пренаписва с <> ALL
Проверете EXPLAIN
изход за всяка заявка, за да видите сами. Това доказва две неща:
IN
никога не може да бъде по-бърз от= ANY
.= ANY
няма да бъде значително по-бързо.
Изборът трябва да се реши откакво е по-лесно за предоставяне :списък със стойности или масив (евентуално като литерал на масива - една стойност).
Ако идентификаторите, които ще предадете, идватот БДа така или иначе е много по-ефективно да ги изберете директно (подзаявка) или да интегрирате изходната таблица в заявката с JOIN
(харесвам @mu коментира).
За да преминете дълъг списък на стойностите от вашия клиент и получете най-доброто производителност , използвайте масив, unnest()
и се присъединете или го предоставете като табличен израз с помощта на VALUES
(като коментира @PinnyM). Но имайте предвид, че JOIN
запазва възможни дубликати в предоставения масив / задайте докато IN
или = ANY
Недей. Още:
- Оптимизиране на заявка в Postgres с голям IN
При наличие на NULL стойности, NOT IN
често е грешен избор и NOT EXISTS
би било правилно (и по-бързо):
- Изберете редове, които не присъстват в друга таблица
Синтаксис за = ANY
За израза на масива Postgres приема:
- конструктор на масив (масивът е конструиран от списък със стойности от страната на Postgres) във формата:
ARRAY[1,2,3]
- или литерал на масив от формата
'{1,2,3}'
.
За да избегнете невалидни прехвърляния на тип, можете да предавате изрично:
ARRAY[1,2,3]::numeric[]
'{1,2,3}'::bigint[]
Свързано:
- PostgreSQL:Проблем с предаването на масив към процедура
- Как да предам масив от персонализиран тип на функцията Postgres
Или можете създайте функция Postgres, като вземете VARIADIC
параметър, който приема отделни аргументи и формира масив от тях:
- Предаване на множество стойности в един параметър
Как да предам масива от Ruby?
Ако приемем id
да бъде integer
:
MyModel.where('id = ANY(ARRAY[?]::int[])', ids.map { |i| i})
Но аз просто се занимавам с Ruby. @mu предоставя подробни инструкции в този свързан отговор:
- Изпращате ли масив от стойности към sql заявка в ruby?