Sqlalchemy join连表查询

摘要1:https://blog.csdn.net/weixin_33804582/article/details/92471702
摘要2:https://www.cnblogs.com/juandx/p/5442752.html
摘要3:https://www.cnblogs.com/wuheng-123/p/9719812.html

model存在外键做join连接

首先创建数据库,在这里一个user对应多个address,因此需要在address上增加user_id这个外键(一对多)。


from sqlalchemy import create_engine
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy import ForeignKey
from sqlalchemy.orm import backref
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
 
Base = declarative_base()
 
 
class User(Base):
    __tablename__ = 'users'
 
    id = Column(Integer, primary_key=True)
    name = Column(String(32))

    addresses = relationship("Address", order_by="Address.id", backref="user")
 
class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, primary_key=True)
    email_address = Column(String(32), nullable=False)
    user_id = Column(Integer, ForeignKey('users.id'))
 
    #user = relationship("User", backref=backref('addresses', order_by=id))
 
engine  = create_engine('mysql://root:root@localhost:3306/test', echo=True)
#Base.metadata.create_all(engine)

1.如果不使用join的话,可以直接联表查询

>>> session.query(User.name, Address.email_address).filter(User.id==Address.user_id).filter(Address.email_address=='test@test.com').all()
2015-08-19 14:02:02,877 INFO sqlalchemy.engine.base.Engine SELECT users.name AS users_name, addresses.email_address AS addresses_email_address 
FROM users, addresses 
WHERE users.id = addresses.user_id AND addresses.email_address = %s
2015-08-19 14:02:02,878 INFO sqlalchemy.engine.base.Engine ('test@test.com',)
[('jack', 'test@test.com')]

2.使用sqlalchemy中提供了Queqy.join()函数

>>> session.query(User).join(Address).filter(Address.email_address=='test@test.com').first()
2015-08-19 14:06:56,624 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name 
FROM users INNER JOIN addresses ON users.id = addresses.user_id 
WHERE addresses.email_address = %s 
 LIMIT %s
2015-08-19 14:06:56,624 INFO sqlalchemy.engine.base.Engine ('test@test.com', 1)
<demo.User object at 0x7f9a74139a10>

model不存在外键做join连接

1.上面的用法的前提是存在外键的情况下,如果没有外键,如何做join连接

from sqlalchemy import create_engine
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy import ForeignKey
from sqlalchemy.orm import backref
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
 
Base = declarative_base()
 
class User(Base):
    __tablename__ = 'users'
 
    id = Column(Integer, primary_key=True)
    name = Column(String(32)) 
 
class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, primary_key=True)
    email_address = Column(String(32), nullable=False)
    user_id = Column(Integer, ForeignKey('users.id'))
 
    #user = relationship("User", backref=backref('addresses', order_by=id))
 
engine  = create_engine('mysql://root:root@localhost:3306/test', echo=True)
#Base.metadata.create_all(engine)
# 上面model对应示例
query.join(Address, User.id==Address.user_id)


# 其他sql示例
result = session.query(User.username,func.count(Article.id)).join(Article,User.id==Article.uid).\
    group_by(User.id).order_by(func.count(Article.id).desc()).all()
print(result)#[('ketang', 2), ('zhiliao', 1)]

'''
SELECT user.username AS user_username, count(article.id) AS count_1 
FROM user INNER JOIN article ON user.id = article.uid GROUP BY user.id ORDER BY count(article.id)
'''

子查询示例

# 原生sql,子表查询
mysql> SELECT users.*, adr_count.address_count FROM users LEFT OUTER JOIN
    ->     (SELECT user_id, count(*) AS address_count
    ->         FROM addresses GROUP BY user_id) AS adr_count
    ->     ON users.id=adr_count.user_id;
+----+------+---------------+
| id | name | address_count |
+----+------+---------------+
|  1 | jack |             2 |
+----+------+---------------+
1 row in set (0.00 sec)

使用sqlalchemy子查询


# 生成子句,等同于(select user_id ... group_by user_id)
>>> sbq = session.query(Address.user_id, func.count('*').label('address_count')).group_by(Address.user_id).subquery()
 
# 联接子句,注意子句中需要使用c来调用字段内容
>>> session.query(User.name, sbq.c.address_count).outerjoin(sbq, User.id==sbq.c.user_id).all()
2015-08-19 14:42:53,425 INFO sqlalchemy.engine.base.Engine SELECT users.name AS users_name, anon_1.address_count AS anon_1_address_count
FROM users LEFT OUTER JOIN (SELECT addresses.user_id AS user_id, count(%s) AS address_count
FROM addresses GROUP BY addresses.user_id) AS anon_1 ON users.id = anon_1.user_id
2015-08-19 14:42:53,425 INFO sqlalchemy.engine.base.Engine ('*',)
[('jack', 2L)]
>>>
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 中,可以使用 ORM 进行关系数据库的操作。当需要进行连表查询时,可以使用 SQLAlchemyjoin() 方法来实现。 首先,需要导入必要的模块: ```python from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine, join from sqlalchemy.ext.declarative import declarative_base ``` 其中,create_engine() 方法用于创建一个数据库引擎,sessionmaker() 方法用于创建一个数据库会话,declarative_base() 方法用于创建一个基类,该基类可以被所有的 ORM 类继承。 然后,需要定义 ORM 类: ```python Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String) email = Column(String) address = Column(String) phone = Column(String) class Order(Base): __tablename__ = 'orders' id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey('users.id')) product = Column(String) quantity = Column(Integer) price = Column(Float) ``` 最后,可以通过 join() 方法来实现连表查询: ```python engine = create_engine('mysql+pymysql://user:password@host/dbname?charset=utf8') Session = sessionmaker(bind=engine) session = Session() result = session.query(User, Order).filter(User.id == Order.user_id).all() for user, order in result: print(user.name, order.product) ``` 以上代码会输出每个用户的姓名和他们对应的订单商品名称。 在连表查询时,需要通过 filter() 方法来指定关联条件,这里使用了 User.id 和 Order.user_id 进行关联。在查询结果中,每个元组包含了 User 和 Order 类的实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值