如何在sqlAlchemy模型的联合查询中使用求和和计数 [英] How to use sum and count in a joined query on sqlAlchemy models

查看:843
本文介绍了如何在sqlAlchemy模型的联合查询中使用求和和计数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个工作的SQL,我需要在使用SQLAlchemy作为ORM的工作的Flask应用中表示。我可以表示联接等,但是用总和,计数和其他特定选择元素 u.firstname ||束手无策。 ’’|| u.lastname

I have working SQL that I need to represent in a working Flask app that is using SQLAlchemy as an ORM. I can represent the joins, etc., but am getting nowhere with tying in the sums, counts, and the other specific select element, u.firstname || ' ' || u.lastname.

SQL

select
  u.firstname || ' ' || u.lastname SELLER,
  count(i.id) UNIQUE_ITEMS,
  sum(i.qty) ITEMS_TOTAL,
  sum(i.qty * p.price) ORDER_AMOUNT
from
  orders o
  INNER JOIN order_items i
    on o.id = i.order_id
    and o.campaign_id = 133
  INNER JOIN products p
      ON i.product_id = p.id
  INNER JOIN users u
      ON o.user_id = u.id
GROUP BY u.id
ORDER BY sum(i.qty) DESC, sum(i.qty * p.price) DESC;

以及有效的Flask实施:

and working Flask implementation:

orders = Order.query.filter_by(campaign_id=campaign_id).
  join(OrderItem).
  join(Product).
  join(User).
  order_by(OrderItem.qty.desc())

如果我添加 group_by(User.id)它也抱怨我没有放置 Order 中的所有其他元素。

If I add group_by(User.id) it complains as well that I haven't placed in every other element from Order.

如果功能出了问题,我正在使用Postgres 9.5

In case the functions are the issue, I'm running against a Postgres 9.5

推荐答案

您正在尝试查询 Order ,但这不是您在原始SQL中查询的内容。您需要类似以下内容的

You're trying to query the Order, but that's not what you are querying in your raw SQL. You need something like:

query = session.query(
    (User.first_name + ' ' + User.last_name).label('seller'),
    sa.func.count(OrderItem.id).label('unique_items'),
    sa.func.sum(OrderItem.qty).label('items_total'),
    sa.func.sum(OrderItem.qty * Product.price).label('order_amount'),
).join(OrderItem).join(Product).group_by(User.id).order_by('items_total',
                                                           'order_amount')

在显示您所发生情况的示例中:

To put it all together in an example that shows you what's going on:

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from decimal import Decimal

engine = sa.create_engine('sqlite:///:memory:')
Base = declarative_base()
session = sa.orm.sessionmaker(bind=engine)()

class OrderItem(Base):
    __tablename__ = 'order'

    id = sa.Column('id', sa.Integer, primary_key=True)
    product_id = sa.Column('product_id', sa.Integer, sa.ForeignKey('product.id'))
    user_id = sa.Column('user_id', sa.Integer, sa.ForeignKey('user.id'))
    qty = sa.Column('qty', sa.Integer)

class Product(Base):
    __tablename__ = 'product'

    id = sa.Column('id', sa.Integer, primary_key=True)
    price = sa.Column('price', sa.Numeric(14,2))

class User(Base):
    __tablename__ = 'user'

    id = sa.Column('id', sa.Integer, primary_key=True)
    first_name = sa.Column('first_name', sa.Text)
    last_name = sa.Column('last_name', sa.Text)

Base.metadata.create_all(engine)

engine.echo = True

session.add(User(id=42, first_name='John', last_name='Cleese'))
session.add(User(id=13, first_name='Sir', last_name='Robin'))
session.add(Product(id=1, price=Decimal('2.10')))
session.add(OrderItem(product_id=1, user_id=42, qty=9))
session.add(OrderItem(product_id=1, user_id=42, qty=2))
session.add(OrderItem(product_id=1, user_id=13, qty=2))
session.add(OrderItem(product_id=1, user_id=13, qty=3))
session.add(OrderItem(product_id=1, user_id=13, qty=20))
session.commit()

query = session.query(
    (User.first_name + ' ' + User.last_name).label('seller'),
    sa.func.count(OrderItem.id).label('unique_items'),
    sa.func.sum(OrderItem.qty).label('items_total'),
    sa.func.sum(OrderItem.qty * Product.price).label('order_amount'),
).join(OrderItem).join(Product).group_by(User.id).order_by('items_total',
                                                           'order_amount')


print('{0:=^40}\n{1:^40}\n{0:=^40}'.format('=', 'Query'))
results = [row for row in session.execute(query)]
print('{0:=^40}\n{1:^40}\n{0:=^40}'.format('=', 'Results'))
for row in results:
    print(dict(row))

这篇关于如何在sqlAlchemy模型的联合查询中使用求和和计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆