SQLAlchemy: วิธีการกรองฟิลด์วันที่?


105

นี่คือโมเดล:

class User(Base):
    ...
    birthday = Column(Date, index=True)   #in database it's like '1987-01-17'
    ...

ฉันต้องการกรองระหว่างวันที่สองวันเช่นเลือกผู้ใช้ทั้งหมดในช่วง 18-30 ปี

จะใช้กับ SQLAlchemy ได้อย่างไร?

ฉันนึกถึง:

query = DBSession.query(User).filter(
    and_(User.birthday >= '1988-01-17', User.birthday <= '1985-01-17')
) 

# means age >= 24 and age <= 27

ฉันรู้ว่าสิ่งนี้ไม่ถูกต้อง แต่จะแก้ไขอย่างไร?

คำตอบ:


181

ในความเป็นจริงคำถามของคุณถูกต้องยกเว้นการพิมพ์ผิด: ตัวกรองของคุณไม่รวมบันทึกทั้งหมด: คุณควรเปลี่ยน<=for >=และในทางกลับกัน:

qry = DBSession.query(User).filter(
        and_(User.birthday <= '1988-01-17', User.birthday >= '1985-01-17'))
# or same:
qry = DBSession.query(User).filter(User.birthday <= '1988-01-17').\
        filter(User.birthday >= '1985-01-17')

นอกจากนี้คุณสามารถใช้between:

qry = DBSession.query(User).filter(User.birthday.between('1985-01-17', '1988-01-17'))

28
Btw แทนที่จะ'1985-01-17'ใช้datetime.date(1985, 1, 17)- อาจจะง่ายกว่าในการเข้าทำงานหรือทำงานกับบางสภาพแวดล้อม
tossbyte

5
@rippleslash: คุณถูกต้องและควรใช้ชนิดข้อมูลที่เหมาะสมสำหรับพารามิเตอร์ อย่างไรก็ตามฐานข้อมูลทั้งหมดยังเข้าใจรูปแบบ ISO 8601 สำหรับวันที่ซึ่งเป็นคำสั่งทางศัพท์ด้วย ด้วยเหตุนี้สำหรับตัวอย่างง่ายๆโดยทั่วไปฉันใช้วันที่จัดรูปแบบ ISO - อ่านง่ายกว่า
รถตู้

4
from app import SQLAlchemyDB as db

Chance.query.filter(Chance.repo_id==repo_id, 
                    Chance.status=="1", 
                    db.func.date(Chance.apply_time)<=end, 
                    db.func.date(Chance.apply_time)>=start).count()

มันเท่ากับ:

select
   count(id)
from
   Chance
where
   repo_id=:repo_id 
   and status='1'
   and date(apple_time) <= end
   and date(apple_time) >= start

ความปรารถนาสามารถช่วยคุณได้


3

หากคุณต้องการรับช่วงเวลาทั้งหมด :

    from sqlalchemy import and_, func

    query = DBSession.query(User).filter(and_(func.date(User.birthday) >= '1985-01-17'),\
                                              func.date(User.birthday) <= '1988-01-17'))

นั่นหมายถึงช่วง: 1985-01-17 00:00 - 1988-01-17 23:59 น


อันตราย:แม้ว่าเรื่องนี้อาจจะเห็นได้ชัดบาง - งานนี้เท่านั้นเพราะfunc.dateไม่CASTในคอลัมน์ที่เอาเวลาจากสมการ => นี้จะไม่ได้ช่วงค่าเฉลี่ยกับเวลา! สิ่งนี้ใช้ได้เฉพาะเมื่อเวลาไม่อยู่ในคอลัมน์ - คุณต้องแคสต์เป็น Date เช่นนี้หรือสร้างคอลัมน์ Date เมื่อเป็น DateTime หรือ timestamp - โดยปกติจะเสร็จสิ้นด้วย 00:00 (ทั้ง MySQL และ PostgreSQL ทำสิ่งนี้) วิธีแก้ปัญหาทั่วไปอื่น ๆ ไม่ได้เป็นการส่ง แต่กำหนดวันที่ที่คุณจะส่งเป็น. endOfDay () ดังนั้นคุณจึงส่ง1988-01-17 23:59:59ไปยังฐานข้อมูลเปรียบเทียบ :)
jave.web
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.