Cláusula SQLAlchemy IN


237

Estoy tratando de hacer esta consulta en sqlalchemy

SELECT id, name FROM user WHERE id IN (123, 456)

Me gustaría vincular la lista [123, 456]en el momento de la ejecución.

Respuestas:


332

Qué tal si

session.query(MyUserClass).filter(MyUserClass.id.in_((123,456))).all()

editar : sin el ORM, sería

session.execute(
    select(
        [MyUserTable.c.id, MyUserTable.c.name], 
        MyUserTable.c.id.in_((123, 456))
    )
).fetchall()

select()toma dos parámetros, el primero es una lista de campos para recuperar, el segundo es la wherecondición. Puede acceder a todos los campos en un objeto de tabla a través de la propiedad c(o columns).


66
Actualmente no estoy usando la parte ORM de sqlachemy, sino solo la API de expresión de SQL.
wonzbak

136

Suponiendo que use el estilo declarativo (es decir, clases ORM), es bastante fácil:

query = db_session.query(User.id, User.name).filter(User.id.in_([123,456]))
results = query.all()

db_sessiones su sesión de base de datos aquí, mientras que Useres la clase ORM con __tablename__igual a "users".


29
Use ~( ~User.id.in_([123,456])) o not_from sqlalchemy.sql.expression( not_(User.id.in_([123,456]))).
Xion


38

Una forma alternativa es usar el modo SQL sin procesar con SQLAlchemy, yo uso SQLAlchemy 0.9.8, python 2.7, MySQL 5.X y MySQL-Python como conector, en este caso, se necesita una tupla. Mi código se enumera a continuación:

id_list = [1, 2, 3, 4, 5] # in most case we have an integer list or set
s = text('SELECT id, content FROM myTable WHERE id IN :id_list')
conn = engine.connect() # get a mysql connection
rs = conn.execute(s, id_list=tuple(id_list)).fetchall()

Espero que todo funcione para ti.


55
Si usa SQL sin formato para consultas tan simples, es mejor que use psycopg2 u otro conector directamente.
omikron

6

Con la expresión API, que según los comentarios es lo que esta pregunta está pidiendo, puede usar el in_método de la columna correspondiente.

Para consultar

SELECT id, name FROM user WHERE id in (123,456)

utilizar

myList = [123, 456]
select = sqlalchemy.sql.select([user_table.c.id, user_table.c.name], user_table.c.id.in_(myList))
result = conn.execute(select)
for row in result:
    process(row)

Esto supone eso user_tabley connha sido definido apropiadamente.


1

Solo quería compartir mi solución usando sqlalchemy y pandas en python 3. Quizás, sería útil.

import sqlalchemy as sa
import pandas as pd
engine = sa.create_engine("postgresql://postgres:my_password@my_host:my_port/my_db")
values = [val1,val2,val3]   
query = sa.text(""" 
                SELECT *
                FROM my_table
                WHERE col1 IN :values; 
""")
query = query.bindparams(values=tuple(values))
df = pd.read_sql(query, engine)

-2

Solo una adición a las respuestas anteriores.

Si desea ejecutar un SQL con una declaración "IN", puede hacer esto:

ids_list = [1,2,3]
query = "SELECT id, name FROM user WHERE id IN %s" 
args = [(ids_list,)] # Don't forget the "comma", to force the tuple
conn.execute(query, args)

Dos puntos:

  • No hay necesidad de paréntesis para la instrucción IN (como "... IN (% s)"), simplemente ponga "... IN% s"
  • Fuerce la lista de sus identificadores para que sea un elemento de una tupla. No olvides el ",": (ids_list,)

EDITAR ¡ Cuidado que si la longitud de la lista es uno o cero, esto generará un error!


2
Creo que deberías hacerlo args = [(tuple(ids_list),)], por favor revisa dos veces .
zs2020

44
El OP pregunta cómo hacer esto en sqlalchemy, sin usar la llamada dbapi sin procesar ...
cowbert

Esto no funciona con una sola lista de elementos, ya que produce (item, )y es incorrecta en SQL
danius
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.