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.

wonzbak
fuente

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).

Simón
fuente
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".

Xion
fuente
29
Use ~( ~User.id.in_([123,456])) o not_from sqlalchemy.sql.expression( not_(User.id.in_([123,456]))).
Xion
1
Aquí hay un enlace al documento .
Sergey Markelov
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.

Jet Yang
fuente
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.

Carl
fuente
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)
dmitry
fuente
-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!

Majid
fuente
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