Istnieją dwa warianty IN wyrażenia:
expression IN (subquery)expression IN (value [, ...])
Podobnie dwa warianty z ANY konstrukcja:
expression operator ANY (subquery)expression operator ANY (array expression)
Podzapytanie działa dla obu technik, ale dla drugiej forma każdego, IN oczekuje listy wartości (zgodnie z definicją w standardowym SQL), gdy = ANY oczekuje tablicy .
Którego użyć?
ANY jest późniejszym, bardziej wszechstronnym dodatkiem, można go łączyć z dowolnym operatorem binarnym zwracającym wartość logiczną. IN spala się do specjalnego przypadku ANY . W rzeczywistości jego druga forma została przepisana wewnętrznie:
IN jest przepisany z = ANY NOT IN jest przepisany za pomocą <> ALL
Sprawdź EXPLAIN dane wyjściowe dla dowolnego zapytania, aby zobaczyć na własne oczy. Dowodzi to dwóch rzeczy:
INnigdy nie może być szybszy niż= ANY.= ANYnie będzie znacznie szybszy.
O wyborze powinno decydować co jest łatwiejsze do dostarczenia :lista wartości lub tablica (ewentualnie jako literał tablicy - pojedyncza wartość).
Jeśli identyfikatory, które zamierzasz przekazać, pochodzą z bazy danych w każdym razie, znacznie wydajniej jest wybrać je bezpośrednio (podzapytanie) lub zintegrować tabelę źródłową z zapytaniem za pomocą JOIN (jak skomentował @mu).
Aby przekazać długą listę wartości od swojego klienta i uzyskaj najlepszą wydajność , użyj tablicy, unnest() i dołącz lub podaj jako wyrażenie tabelowe za pomocą VALUES (jak skomentował @PinnyM). Pamiętaj jednak, że JOIN zachowuje możliwe duplikaty w podanej tablicy / ustaw podczas IN lub = ANY nie rób. Więcej:
- Optymalizacja zapytania Postgres z dużym IN
W obecności wartości NULL, NOT IN jest często złym wyborem i NOT EXISTS miałby rację (i szybciej):
- Wybierz wiersze, których nie ma w innej tabeli
Składnia dla = ANY
Dla wyrażenia tablicowego Postgres akceptuje:
- konstruktor tablicowy (tablica jest skonstruowana z listy wartości po stronie Postgres) postaci:
ARRAY[1,2,3] - lub literał tablicowy w postaci
'{1,2,3}'.
Aby uniknąć rzutowania nieprawidłowych typów, możesz jawnie rzutować:
ARRAY[1,2,3]::numeric[]
'{1,2,3}'::bigint[]
Powiązane:
- PostgreSQL:problem z przekazywaniem tablicy do procedury
- Jak przekazać tablicę typów niestandardowych do funkcji Postgres
Albo możesz utwórz funkcję Postgres biorąc VARIADIC parametr, który pobiera poszczególne argumenty i tworzy z nich tablicę:
- Przekazywanie wielu wartości w jednym parametrze
Jak przekazać tablicę z Rubiego?
Zakładając id być integer :
MyModel.where('id = ANY(ARRAY[?]::int[])', ids.map { |i| i})
Ale po prostu gram w Ruby. @mu zawiera szczegółowe instrukcje w tej powiązanej odpowiedzi:
- Wysyłasz tablicę wartości do zapytania sql w ruby?