sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo usar ANY en lugar de IN en una cláusula WHERE con Rails?

Hay dos variantes de IN expresiones:

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

Del mismo modo, dos variantes con ANY construir:

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

Una subconsulta funciona para cualquier técnica, pero para el segundo forma de cada uno, IN espera una lista de valores (como se define en SQL estándar) while = ANY espera una matriz .

¿Cuál usar?

ANY es una adición posterior y más versátil, se puede combinar con cualquier operador binario que devuelva un valor booleano. IN se reduce a un caso especial de ANY . De hecho, su segunda forma se reescribe internamente:

IN se reescribe con = ANY
NOT IN se reescribe con <> ALL

Compruebe el EXPLAIN salida para cualquier consulta para ver por ti mismo. Esto prueba dos cosas:

  • IN nunca puede ser más rápido que = ANY .
  • = ANY no va a ser sustancialmente más rápido.

La elección debe decidirse por qué es más fácil de proporcionar :una lista de valores o una matriz (posiblemente como una matriz literal - un solo valor).

Si las identificaciones que va a pasar provienen de dentro de la base de datos de todos modos, es mucho más eficiente seleccionarlos directamente (subconsulta) o integrar la tabla de origen en la consulta con JOIN (como comentó @mu).

Para pasar una lista larga de valores de su cliente y obtenga el mejor rendimiento , usa una matriz, unnest() y únase, o proporciónelo como expresión de tabla usando VALUES (como comentó @PinnyM). Pero tenga en cuenta que un JOIN conserva posibles duplicados en la matriz / conjunto proporcionado mientras IN o = ANY no. Más:

  • Optimización de una consulta de Postgres con un IN grande

En presencia de valores NULL, NOT IN es a menudo la elección incorrecta y NOT EXISTS sería correcto (y más rápido también):

  • Seleccionar filas que no están presentes en otra tabla

Sintaxis para = ANY

Para la expresión de matriz, Postgres acepta:

  • un constructor de matriz (la matriz se construye a partir de una lista de valores en el lado de Postgres) de la forma:ARRAY[1,2,3]
  • o una matriz literal de la forma '{1,2,3}' .

Para evitar conversiones de tipos no válidos, puede convertir explícitamente:

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

Relacionado:

  • PostgreSQL:Problema al pasar la matriz al procedimiento
  • Cómo pasar una matriz de tipo personalizada a la función de Postgres

O usted podría crear una función de Postgres tomando un VARIADIC parámetro, que toma argumentos individuales y forma una matriz a partir de ellos:

  • Pasar múltiples valores en un solo parámetro

¿Cómo pasar la matriz de Ruby?

Asumiendo id ser integer :

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

Pero solo estoy incursionando en Ruby. @mu proporciona instrucciones detalladas en esta respuesta relacionada:

  • ¿Enviar una matriz de valores a una consulta sql en ruby?