Python中如何使用sqlalchemy进行join操作?

想要按用户取出产品的价格
原 SQL 工作语句
select pro.id as id,
pro.name as name,
pri.year1 as year1
from prices pri right outer join products pro on pri.product_id = pro.id where user_group_id=(select user_group_id from user_relationships where user_id=2);



搞了一晚上了,还是没能成功转成 sqlalchemy 查询方法。
products = Product.query.outerjoin(Price).filter_by(user_group_id=2)

sqlalchemy 构建的句子是这样,没有返回价格信息,
SELECT products.id AS products_id, products.name AS products_name, products.time_created AS products_time_created, products.time_updated AS products_time_updated
FROM products LEFT OUTER JOIN prices ON products.id = prices.product_id
WHERE prices.user_group_id = %s
Python中如何使用sqlalchemy进行join操作?


3 回复

在SQLAlchemy里做JOIN操作,核心就是用query()配合join()方法。假设你有UserOrder两个表,通过user_id关联,下面是一个完整的例子:

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    orders = relationship("Order", back_populates="user")

class Order(Base):
    __tablename__ = 'orders'
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('users.id'))
    product = Column(String)
    user = relationship("User", back_populates="orders")

engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# 插入测试数据
user1 = User(name="Alice")
session.add(user1)
session.add(Order(user=user1, product="Book"))
session.commit()

# INNER JOIN: 查询所有订单及对应的用户名
results = session.query(Order, User.name).join(User, Order.user_id == User.id).all()
for order, user_name in results:
    print(f"Order ID: {order.id}, Product: {order.product}, User: {user_name}")

# 如果你定义了relationship,可以直接通过它来join,更简洁
results2 = session.query(Order).join(Order.user).all()
for order in results2:
    print(f"Order ID: {order.id}, User: {order.user.name}")

# LEFT OUTER JOIN 使用 outerjoin()
results3 = session.query(User.name, Order.product).outerjoin(Order, User.id == Order.user_id).all()
for user_name, product in results3:
    print(f"User: {user_name}, Product: {product or 'No orders'}")

关键点:

  1. 基本JOINsession.query(...).join(目标表, 关联条件)
  2. 使用relationship:如果模型里定义了relationship,可以直接join(模型类.relationship属性),SQLAlchemy会自动推导关联条件。
  3. LEFT JOIN:把join()换成outerjoin()就行。
  4. 选择字段:在query()里指定你要的字段或模型,比如query(Order, User.name)

总结:用join()方法,配合模型关系让代码更简洁。


1.你的写法无法查出 Price 是因为你 query 的对象仅仅是 Product,尽管你做了显式 join,但是 SQLAlchemy 只会返回 Product 的信心。

2. 正确的写法有很多种,具体要看你的 Product, Price, User 三个 model 类是怎样建立 SQLAlchemy relationships 的。

其中一种最简单的写法,不管你三个类是什么关系都能用的写法,是隐式 jcross join: session.query(Product, Price).filter(Product.id == Price.id & Price.user_group_id == 2)

今天又搞了几小时弄好了
用 model 开始的查询 只返回 model 表的数据。 改用 db.session.query 并设置了别名

回到顶部