Clause SQLAlchemy IN

237

J'essaie de faire cette requête dans sqlalchemy

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

Je voudrais lier la liste [123, 456]au moment de l'exécution.

wonzbak
la source

Réponses:

332

Que diriez-vous

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

edit : Sans l'ORM, ce serait

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

select()prend deux paramètres, le premier est une liste de champs à récupérer, le second est la wherecondition. Vous pouvez accéder à tous les champs d'un objet table via la propriété c(ou columns).

Simon
la source
6
Je n'utilise pas actuellement la partie ORM de sqlachemy, mais seulement l'API SQL Expression.
wonzbak
136

En supposant que vous utilisez le style déclaratif (c'est-à-dire les classes ORM), c'est assez simple:

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

db_sessionest votre session de base de données ici, tandis que Userla classe ORM est __tablename__égale à "users".

Xion
la source
29
Utilisez ~( ~User.id.in_([123,456])) ou not_depuis sqlalchemy.sql.expression( not_(User.id.in_([123,456]))).
Xion
1
Voici un lien vers le doc .
Sergey Markelov
38

Une autre manière est d'utiliser le mode SQL brut avec SQLAlchemy, j'utilise SQLAlchemy 0.9.8, python 2.7, MySQL 5.X et MySQL-Python comme connecteur, dans ce cas, un tuple est nécessaire. Mon code ci-dessous:

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

J'espère que tout fonctionne pour vous.

Jet Yang
la source
5
Si vous utilisez du SQL brut pour de telles requêtes simples, il vaut mieux utiliser directement psycopg2 ou un autre connecteur.
omikron
6

Avec l'expression API, qui, sur la base des commentaires, est ce que cette question demande, vous pouvez utiliser la in_méthode de la colonne appropriée.

Pour interroger

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

utilisation

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)

Cela suppose que user_tableet connont été définis de manière appropriée.

Carl
la source
1

Je voulais juste partager ma solution en utilisant sqlalchemy et pandas en python 3. Peut-être, on le trouverait utile.

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
la source
-2

Juste un ajout aux réponses ci-dessus.

Si vous souhaitez exécuter un SQL avec une instruction "IN", vous pouvez le faire:

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)

Deux points:

  • Il n'y a pas besoin de parenthèses pour l'instruction IN (comme "... IN (% s)"), mettez simplement "... IN% s"
  • Forcez la liste de vos identifiants à être un élément d'un tuple. N'oubliez pas le ",": (ids_list,)

EDIT Attention, si la longueur de la liste est de un ou zéro, cela provoquera une erreur!

Majid
la source
2
Je pense que vous devriez le faire args = [(tuple(ids_list),)], veuillez vérifier.
zs2020
4
L'OP demande comment faire cela dans sqlalchemy, sans utiliser d'appel dbapi brut ...
cowbert
Cela ne fonctionne pas avec une seule liste d'éléments car elle produit (item, )et elle est incorrecte dans SQL
danius