SQLAlchemy IN klausa

237

Saya mencoba melakukan kueri ini di sqlalchemy

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

Saya ingin mengikat daftar [123, 456]pada waktu eksekusi.

wonzbak
sumber

Jawaban:

332

Bagaimana tentang

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

sunting : Tanpa ORM, itu akan menjadi

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

select()mengambil dua parameter, yang pertama adalah daftar bidang yang akan diambil, yang kedua adalah wherekondisi. Anda bisa mengakses semua bidang pada objek tabel melalui properti c(atau columns).

Simon
sumber
6
Saat ini saya tidak menggunakan bagian ORM dari sqlachemy, tetapi hanya SQL Expression API.
wonzbak
136

Dengan asumsi Anda menggunakan gaya deklaratif (yaitu kelas ORM), itu cukup mudah:

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

db_sessionadalah sesi basis data Anda di sini, sedangkan Userkelas ORM dengan __tablename__sama dengan "users".

Xion
sumber
29
Gunakan ~( ~User.id.in_([123,456])) atau not_dari sqlalchemy.sql.expression( not_(User.id.in_([123,456]))).
Xion
1
Berikut ini tautan ke dokumen tersebut .
Sergey Markelov
38

Cara alternatif adalah menggunakan mode SQL mentah dengan SQLAlchemy, saya menggunakan SQLAlchemy 0.9.8, python 2.7, MySQL 5.X, dan MySQL-Python sebagai konektor, dalam hal ini, diperlukan sebuah tuple. Kode saya tercantum di bawah ini:

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

Semoga semuanya berhasil untuk Anda.

Jet Yang
sumber
5
Jika Anda menggunakan SQL mentah untuk pertanyaan sederhana seperti itu, Anda lebih baik menggunakan psycopg2 atau konektor lain secara langsung.
omikron
6

Dengan API ekspresi, yang berdasarkan pada komentar adalah apa yang ditanyakan oleh pertanyaan ini, Anda dapat menggunakan in_metode kolom yang relevan.

Ke kueri

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

menggunakan

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)

Ini mengasumsikan bahwa user_tabledan conntelah didefinisikan secara tepat.

Carl
sumber
1

Hanya ingin berbagi solusi saya menggunakan sqlalchemy dan panda di python 3. Mungkin, orang akan merasa berguna.

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
sumber
-2

Hanya tambahan jawaban di atas.

Jika Anda ingin menjalankan SQL dengan pernyataan "IN" Anda bisa melakukan ini:

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)

Dua poin:

  • Tidak perlu Parenthesis untuk pernyataan IN (seperti "... IN (% s)"), cukup cantumkan "... IN% s"
  • Paksa daftar id Anda menjadi salah satu elemen tuple. Jangan lupa tanda ",": (ids_list,)

EDIT Perhatikan bahwa jika panjang daftar adalah satu atau nol, ini akan menimbulkan kesalahan!

Majid
sumber
2
Saya pikir Anda harus melakukannya args = [(tuple(ids_list),)], periksa kembali.
zs2020
4
OP bertanya bagaimana melakukan ini dalam sqlalchemy, tidak menggunakan panggilan dbapi mentah ...
cowbert
Ini tidak berfungsi dengan daftar item tunggal karena menghasilkan (item, )dan itu tidak benar dalam SQL
danius