Klauzula SQLAlchemy IN


237

Próbuję wykonać to zapytanie w sqlalchemy

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

Chciałbym powiązać listę [123, 456]w czasie wykonywania.

Odpowiedzi:


332

Co powiesz na

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

edycja : Bez ORM byłoby to

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

select()zajmuje dwa parametry, pierwszy to lista pól do pobrania, drugi to wherewarunek. Możesz uzyskać dostęp do wszystkich pól w obiekcie tabeli za pośrednictwem właściwości c(lub columns).


6
Obecnie nie używam części ORM narzędzia sqlachemy, ale tylko interfejs API wyrażeń SQL.
wonzbak

136

Zakładając, że używasz stylu deklaratywnego (tj. Klas ORM), jest to dość łatwe:

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

db_sessionjest tutaj twoja sesja bazy danych, podczas Usergdy klasa ORM jest __tablename__równa "users".


29
Użyj ~( ~User.id.in_([123,456])) lub not_from sqlalchemy.sql.expression( not_(User.id.in_([123,456]))).
Xion


38

Alternatywnym sposobem jest użycie surowego trybu SQL z SQLAlchemy, używam SQLAlchemy 0.9.8, python 2.7, MySQL 5.X i MySQL-Python jako łącznika, w tym przypadku potrzebna jest krotka. Mój kod wymieniony poniżej:

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

Mam nadzieję, że wszystko działa dla Ciebie.


5
Jeśli używasz surowego SQL do takich prostych zapytań, lepiej jest użyć psycopg2 lub innego konektora bezpośrednio.
omikron,

6

Dzięki API wyrażenia, które na podstawie komentarzy jest tym, o co pyta to pytanie, możesz użyć in_metody odpowiedniej kolumny.

Zapytać

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

posługiwać się

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)

Zakłada się to user_tablei connodpowiednio zdefiniowano.


1

Chciałem tylko udostępnić moje rozwiązanie za pomocą sqlalchemy i pand w Pythonie 3. Być może przydałoby się to.

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

Tylko dodatek do powyższych odpowiedzi.

Jeśli chcesz wykonać SQL z instrukcją „IN”, możesz to zrobić:

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)

Dwa punkty:

  • Nie ma potrzeby nawiasów dla instrukcji IN (np. „... IN (% s)”), wystarczy wpisać „... IN% s”
  • Wymuś, aby lista twoich identyfikatorów była jednym z elementów krotki. Nie zapomnij o „,”: (ids_list,)

EDYCJA Uważaj, jeśli długość listy wynosi jeden lub zero, spowoduje to błąd!


2
Myślę, że powinieneś to zrobić args = [(tuple(ids_list),)], proszę dokładnie sprawdzić.
zs2020

4
OP pyta, jak to zrobić w sqlalchemy, nie używając surowego wywołania dbapi ...
cowbert

Nie działa to z pojedynczą listą elementów, ponieważ tworzy (item, )i jest niepoprawne w SQL
danius
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.