sql >> Databáze >  >> RDS >> PostgreSQL

Jak použít ANY místo IN v klauzuli WHERE s Rails?

Existují dvě varianty IN výrazy:

  • expression IN (subquery)
  • expression IN (value [, ...])

Podobně dvě varianty s ANY konstrukce:

  • expression operator ANY (subquery)
  • expression operator ANY (array expression)

Dílčí dotaz funguje pro obě techniky, ale na druhou tvar každého, IN očekává seznam hodnot (jak je definováno ve standardním SQL), zatímco = ANY očekává pole .

Který použít?

ANY je pozdější, všestrannější doplněk, lze jej kombinovat s libovolným binárním operátorem vracejícím booleovskou hodnotu. IN vyhoří na speciální případ ANY . Ve skutečnosti je jeho druhá podoba interně přepsána:

IN je přepsán s = ANY
NOT IN je přepsán pomocí <> ALL

Zkontrolujte EXPLAIN výstup pro jakýkoli dotaz, abyste se sami přesvědčili. To dokazuje dvě věci:

  • IN nikdy nemůže být rychlejší než = ANY .
  • = ANY nebude podstatně rychlejší.

O výběru by mělo rozhodnout, co je jednodušší poskytnout :seznam hodnot nebo pole (možná jako literál pole – jedna hodnota).

Pokud ID, která se chystáte předávat, pocházejí z databáze každopádně je mnohem efektivnější vybrat je přímo (poddotaz) nebo integrovat zdrojovou tabulku do dotazu pomocí JOIN (jako komentář @mu).

Chcete-li předat dlouhý seznam hodnot od vašeho klienta a získejte nejlepší výkon , použijte pole, unnest() a připojte se, nebo jej poskytněte jako tabulkový výraz pomocí VALUES (jako komentář @PinnyM). Všimněte si však, že JOIN zachová možné duplikáty v poskytnutém poli / set while IN nebo = ANY ne. Více:

  • Optimalizace dotazu Postgres s velkým IN

V případě hodnot NULL NOT IN je často špatná volba a NOT EXISTS by bylo správné (a také rychlejší):

  • Vyberte řádky, které se nenacházejí v jiné tabulce

Syntaxe pro = ANY

Pro výraz pole Postgres přijímá:

  • konstruktor pole (pole je vytvořeno ze seznamu hodnot na straně Postgresu) ve tvaru:ARRAY[1,2,3]
  • nebo polový literál ve tvaru '{1,2,3}' .

Chcete-li se vyhnout neplatnému přetypování, můžete přetypovat explicitně:

ARRAY[1,2,3]::numeric[]
'{1,2,3}'::bigint[]

Související:

  • PostgreSQL:Problém s předáním pole do procedury
  • Jak předat pole vlastního typu funkci Postgres

Nebo můžete vytvořte funkci Postgres pomocí VARIADIC parametr, který přebírá jednotlivé argumenty a tvoří z nich pole:

  • Předání více hodnot v jednom parametru

Jak předat pole z Ruby?

Za předpokladu id být integer :

MyModel.where('id = ANY(ARRAY[?]::int[])', ids.map { |i| i})

Ale já jen fušuji do Ruby. @mu poskytuje podrobné pokyny v této související odpovědi:

  • Odeslání pole hodnot do dotazu SQL v ruby?



  1. Jak získat aktuální datum na serveru SQL

  2. Důležitost dobrého návrhu databáze (a 7 kroků k jeho dosažení)

  3. Mějte PL/SQL výstupy v reálném čase

  4. Cross Apply xml dotaz funguje exponenciálně horší, jak xml dokument roste