SQLAlchemy複雜查詢

         最近我的用python + flask搞了一個小項目,ORM用到的是SQLAlchemy。python

    SQLAlchemy的查詢方式很是靈活,你所能想像到的複雜SQL 語句,基本上均可以實現。這裏簡單的總結一下經常使用的查詢技巧。sql

  1. 多條件組合,能夠用and_,or_實現。最外層時,and_能夠省略,默認用逗號分開條件。
    db.session.query(User).filter(
            and_(
                or_(User.name==name1,User.name==name2),
                or_(User.status==1,User.status==2)
            ),
            User.active==1
        ).first()

     

  2. 動態組合條件。針對不一樣的場景,可能須要不一樣的查詢條件,相似動態的拼接SQL 語句。
            if filter_type == 1:
                search = and_(GameRoom.status ==1,or_(
                    and_(GameRoom.white_user_id == user_id,
                         GameRoom.active_player == 1),
                    and_(GameRoom.black_user_id == user_id,
                         GameRoom.active_player == 0)))
            elif filter_type == 2:
                search = and_(GameRoom.status ==1,or_(
                    and_(GameRoom.white_user_id == user_id,
                         GameRoom.active_player == 0),
                    and_(GameRoom.black_user_id == user_id,
                         GameRoom.active_player == 1)))
            elif filter_type == 3:
                search = GameRoom.create_by == user_id
            
            db.session.query(GameRoom).filter(search).all()

     

  3. 關聯查詢。對應SQL的join和left join等。
        session.query(User, Address).filter(User.id == Address.user_id).all()
        session.query(User).join(User.addresses).all()
        session.query(User).outerjoin(User.addresses).all()

     

  4. 使用別名用aliased,aliased在orm包中。當要對同一個表使用屢次關聯時,可能須要用到別名。同時,若是查詢的結果有多個同名的字段,能夠使用label重命名。
    black_user = orm.aliased(User)
    white_user = orm.aliased(User)
    db.session.query(
                GameRoom,
                black_user.score.label("black_score"),
                white_user.score.label("white_score")
                ).outerjoin(black_user,GameRoom.black_user_id==black_user.user_id).outerjoin(
                    white_user,GameRoom.white_user_id==white_user.user_id).filter(
                        GameRoom.id==room_id
                ).all()

     

  5. 聚合查詢和使用數據庫函數。func能夠調用各類聚合函數,和當前數據庫支持的其它函數。
    session.query(User.name, func.count('*').label("user_count")).group_by(User.name).all()
    
    session.query(User.name, func.sum(User.id).label("user_id_sum")).filter(func.to_days(User.create_date)==func.to_days(func.now())).group_by(User.name).all()

     

  6.  子查詢。 數據庫

    stmt = db.session.query(Address.user_id, func.count('*').label("address_count")).group_by(Address.user_id).subquery()
    db.session.query(User, stmt.c.address_count).outerjoin((stmt, User.id == stmt.c.user_id)).order_by(User.id).all()

     

  7. 直接運行SQL語句查詢。若是查詢實在太複雜,以爲用SQLAlchemy查詢方式很難實現,或者要經過存儲過程實現查詢,能夠讓SQLAlchemy直接運行SQL語句返回結果。
            sql ="""select b.user_id,b.user_name,b.icon,b.score,a.add_score from
                (select user_id, sum(score_new - score_old) as add_score from user_score_log
                where year(create_date)=year(now()) and month(create_date)=month(now())
                group by user_id) a join users b on a.user_id=b.user_id
                order by a.add_score desc limit 50"""
            list_top = db.session.execute(sql).fetchall()

      

  8. 分頁查詢。sqlalchemy中分頁用到pagination,先不說性能怎麼樣,使用起來是真的很是方便。
            pagination = GameMessage.query.filter(GameMessage.game_id==game_id).\
                order_by(GameMessage.id.desc()).\
                paginate(page, per_page=20, error_out=True)
            pages = pagination.pages
            total = pagination.total
            items = pagination.items

     

  總的來講,SQLAlchemy是我用過的最好的ORM 框架之一(其實我最熟的是.net,python也只用過這一個ORM工具)。基本上常見的SQL 語句,這裏都已經實現。若是你的查詢實在太複雜的,可能須要用存儲過程來實現,直接運行SQL也不失爲一種簡便的方法。flask

相關文章
相關標籤/搜索